diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 568a0001a7f9e6df734a00f6bbb7ad770f265369..b0df61c7e1fee8ba211819b722c4aea9fe7a6623 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ git-debian-10-gcc-7-14: - "cores:20" - "perftool" -git-debian-10-clang-6-libcpp-17: +git-debian-10-clang-7-libcpp-17: image: "registry.dune-project.org/docker/ci/dune-pdelab:git-debian-10-clang-7-libcpp-17" script: duneci-standard-test tags: diff --git a/bin/analyzegrid/analyze_grid.cc b/bin/analyzegrid/analyze_grid.cc index bd19952640f2162ac3fa8cbaab0a51c638862286..24498b6fd4d2c9ba617236beaf5a21218de53d42 100644 --- a/bin/analyzegrid/analyze_grid.cc +++ b/bin/analyzegrid/analyze_grid.cc @@ -55,12 +55,8 @@ int main(int argc, char** argv){ using Grid = Dune::UGGrid<dim>; using GV = Grid::LeafGridView; IniGridFactory<Grid> factory(initree); - std::shared_ptr<Grid> grid = factory.getGrid(); - - // Note: As long as createConsistentGrid drops boundary faces we assume - // that the users already provides a consistent gmsh file. - // std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); - // std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); + std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); + std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); GV gv = grid->leafGridView(); @@ -76,19 +72,15 @@ int main(int argc, char** argv){ using Grid = Dune::UGGrid<dim>; using GV = Grid::LeafGridView; IniGridFactory<Grid> factory(initree); - std::shared_ptr<Grid> grid = factory.getGrid(); - - // Note: As long as createConsistentGrid drops boundary faces we assume - // that the users already provides a consistent gmsh file. - // std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); - // std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); + std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); + std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); GV gv = grid->leafGridView(); // Extract facemod/facedir intersection variation using ES = Dune::PDELab::AllEntitySet<GV>; ES es(gv); - std::cout << "Analyse 3d gmsh grid" << std::endl; + std::cout << "Analyse 2d gmsh grid" << std::endl; analyze_grid(es, filename); } } diff --git a/dune/codegen/sumfact/invertgeometry.hh b/dune/codegen/sumfact/invertgeometry.hh index 2a0b364cc9df2daea9088af053c89a4da129cae2..5ca89b2f2719aae3f01b315ee37a96c66266d4fe 100644 --- a/dune/codegen/sumfact/invertgeometry.hh +++ b/dune/codegen/sumfact/invertgeometry.hh @@ -63,7 +63,7 @@ inline T invert_and_return_determinant(const T a00, const T a10, const T a20, inverse[7] *= t17; inverse[2] = a10 * a21; - inverse[2] += a11 * a20; + inverse[2] -= a11 * a20; inverse[2] *= t17; inverse[5] = t12; diff --git a/python/dune/codegen/pdelab/argument.py b/python/dune/codegen/pdelab/argument.py index 8d3c3a3db6dc623da71cfff7679384712e414196..c3cc48298c1b2efb70c6c7716b29b221486044e1 100644 --- a/python/dune/codegen/pdelab/argument.py +++ b/python/dune/codegen/pdelab/argument.py @@ -106,7 +106,10 @@ def pymbolic_coefficient(container, lfs, index): if not isinstance(lfs, Expression): lfs = Variable(lfs) - return Call(CoefficientAccess(container), (lfs, Variable(index),)) + if isinstance(index, str): + index = Variable(index) + + return Call(CoefficientAccess(container), (lfs, index,)) def type_coefficientcontainer(): diff --git a/python/dune/codegen/pdelab/driver/gridfunctionspace.py b/python/dune/codegen/pdelab/driver/gridfunctionspace.py index 991b770fde66c26c40e713a04e2c05df181ae357..377b304b03499aa3c109390cf72f4af0f6327e9b 100644 --- a/python/dune/codegen/pdelab/driver/gridfunctionspace.py +++ b/python/dune/codegen/pdelab/driver/gridfunctionspace.py @@ -83,16 +83,10 @@ def define_grid(name): # TODO: In principle this is only necessary if we use sum factorization in # one of the operators. So this could be turned off if that is not the case. if isQuadrilateral(get_trial_element().cell()) and get_option("grid_unstructured"): - # TODO: createConsistentGrid drops boundary faces. Instead of using - # this we assume that the user already provides a constistent gmsh - # file. This can be createt by createConsistentGmshFile, see - # dune-codegen/bin/analyzegrid/consistent_gmsh.cc - # include_file("dune/consistent-edge-orientation/createconsistentgrid.hh", filetag="driver") - # return ["IniGridFactory<{}> factory({});".format(_type, ini), - # "std::shared_ptr<{}> grid_nonconsistent = factory.getGrid();".format(_type), - # "std::shared_ptr<{}> grid = createConsistentGrid(grid_nonconsistent);".format(_type)] + include_file("dune/consistent-edge-orientation/createconsistentgrid.hh", filetag="driver") return ["IniGridFactory<{}> factory({});".format(_type, ini), - "std::shared_ptr<{}> grid = factory.getGrid();".format(_type)] + "std::shared_ptr<{}> grid_nonconsistent = factory.getGrid();".format(_type), + "std::shared_ptr<{}> grid = createConsistentGrid(grid_nonconsistent);".format(_type)] return ["IniGridFactory<{}> factory({});".format(_type, ini), "std::shared_ptr<{}> grid = factory.getGrid();".format(_type)] diff --git a/python/dune/codegen/sumfact/accumulation.py b/python/dune/codegen/sumfact/accumulation.py index 3be02ae08e1dd18e0fb942e1755587984fec3755..eeb383da8fcec4d7799a15befa6f38698376fdb5 100644 --- a/python/dune/codegen/sumfact/accumulation.py +++ b/python/dune/codegen/sumfact/accumulation.py @@ -15,6 +15,7 @@ from dune.codegen.generation import (accumulation_mixin, instruction, post_include, kernel_cached, + silenced_warning, temporary_variable, transform, valuearg @@ -30,6 +31,11 @@ from dune.codegen.pdelab.restriction import restricted_name from dune.codegen.pdelab.signatures import assembler_routine_name from dune.codegen.pdelab.geometry import world_dimension from dune.codegen.pdelab.spaces import name_lfs +from dune.codegen.sumfact.permutation import (permute_backward, + permute_forward, + sumfact_cost_permutation_strategy, + sumfact_quadrature_permutation_strategy, + ) from dune.codegen.sumfact.tabulation import (basis_functions_per_direction, construct_basis_matrix_sequence, ) @@ -86,6 +92,7 @@ def accum_iname(element, bound, i): class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord): def __init__(self, + matrix_sequence=None, accumvar=None, restriction=None, test_element=None, @@ -93,7 +100,25 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord): trial_element=None, trial_element_index=None, ): + + # See comment regarding get_keyword_arguments why we assert that matrix_sequence is not None + assert matrix_sequence is not None + + # Note: The function sumfact_quadrature_permutation_strategy does not + # work anymore after the visiting process since get_facedir and + # get_facemod are not well defined. But we need the + # quadrature_permutation to generate the name of the sumfact + # kernel. This means we need to store the value here instead of + # recalculating it in the property. + dim = world_dimension() + quadrature_permutation = sumfact_quadrature_permutation_strategy(dim, restriction[0]) + + # Calculate cost optimal permutation + matrix_sequence = permute_forward(matrix_sequence, quadrature_permutation) + cost_permutation = sumfact_cost_permutation_strategy(matrix_sequence, self.stage) + # TODO: Isnt accumvar superfluous in the presence of all the other infos? + # Note: Do not put matrix_sequence into the Record. That screws up the vectorization strategy! ImmutableRecord.__init__(self, accumvar=accumvar, restriction=restriction, @@ -101,11 +126,34 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord): test_element_index=test_element_index, trial_element=trial_element, trial_element_index=trial_element_index, + _quadrature_permutation=quadrature_permutation, + _cost_permutation=cost_permutation, ) def __repr__(self): return ImmutableRecord.__repr__(self) + def get_keyword_arguments(self): + """Get dictionary of keyword arguments needed to initialize this class + + Extract keyword arguments from the ImmutableRecord and modify + accordingly. You need to set the correct matrix sequence before using + this dict to create an interface. + """ + dict = self.get_copy_kwargs() + del dict['_cost_permutation'] + del dict['_quadrature_permutation'] + dict['matrix_sequence'] = None + return dict + + @property + def quadrature_permutation(self): + return self._quadrature_permutation + + @property + def cost_permutation(self): + return self._cost_permutation + @property def stage(self): return 3 @@ -122,14 +170,46 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord): from dune.codegen.sumfact.basis import SumfactBasisMixin return SumfactBasisMixin.lfs_inames(None, get_leaf(self.trial_element, self.trial_element_index), self.restriction) - def realize(self, sf, result, insn_dep, inames=None, additional_inames=()): + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + # The result of stage 2 has the correct quadrature permutation but no + # cost permutation is applied. The inames for this method are + # quadrature and cost permuted. This means we need to reverse the cost + # permutation to access the result of stage 2 in the correct way. + shape = permute_backward(shape, self.cost_permutation) + inames = permute_backward(inames, self.cost_permutation) + + # Get a temporary that interprets the base storage of the input + # as a column-major matrix. In later iteration of the matrix loop + # this reinterprets the output of the previous iteration. + inp = buf.get_temporary("buff_step0_in", + shape=shape + vec_shape, + dim_tags=ftags, + ) + + # The input temporary will only be read from, so we need to silence + # the loopy warning + silenced_warning('read_no_write({})'.format(inp)) + + return prim.Subscript(prim.Variable(inp), inames + vec_iname) + + def accumulate_output(self, sf, result, insn_dep, inames=None, additional_inames=()): trial_leaf_element = get_leaf(self.trial_element, self.trial_element_index) if self.trial_element is not None else None - basis_size = tuple(mat.basis_size for mat in sf.permuted_matrix_sequence) + # Note: Using matrix_sequence_quadrature_permuted is ok in this place since: + # + # - If the grid is unstructured we assume that the polynomial degree + # for each direction is the same. + # + # - If the grid is structured the quadrature permuted matrix sequence + # is the same as the original one. We still need to call this one + # since VectorizedSumfactKernels do not have the matrix_sequence + # attribute. + basis_size = tuple(mat.basis_size for mat in sf.matrix_sequence_quadrature_permuted) + if get_option('grid_unstructured'): + assert len(set(basis_size)) == 1 if inames is None: - inames = tuple(accum_iname(trial_leaf_element, mat.rows, i) - for i, mat in enumerate(sf.permuted_matrix_sequence)) + inames = tuple(accum_iname(trial_leaf_element, size, i) for i, size in enumerate(basis_size)) # Determine the expression to accumulate with. This depends on the vectorization strategy! from dune.codegen.tools import maybe_wrap_subscript @@ -180,7 +260,10 @@ class AccumulationOutput(SumfactKernelInterfaceBase, ImmutableRecord): return frozenset({dep}) - def realize_direct(self, result, inames, shape, which=0, **args): + def realize_direct_output(self, result, inames, shape, which=0, **args): + inames = permute_backward(inames, self.cost_permutation) + inames = permute_backward(inames, self.quadrature_permutation) + direct_output = "fastdg{}".format(which) ftags = ",".join(["f"] * len(shape)) @@ -452,7 +535,8 @@ def generate_accumulation_instruction(expr, visitor): if priority is None: priority = 3 - output = AccumulationOutput(accumvar=accumvar, + output = AccumulationOutput(matrix_sequence=matrix_sequence, + accumvar=accumvar, restriction=(test_info.restriction, trial_info.restriction), test_element=test_info.element, test_element_index=test_info.element_index, @@ -524,4 +608,4 @@ def generate_accumulation_instruction(expr, visitor): result, insn_dep = realize_sum_factorization_kernel(vsf.copy(insn_dep=vsf.insn_dep.union(insn_dep))) if not get_form_option("fastdg"): - insn_dep = vsf.interface.realize(vsf, result, insn_dep) + insn_dep = vsf.interface.accumulate_output(vsf, result, insn_dep) diff --git a/python/dune/codegen/sumfact/autotune.py b/python/dune/codegen/sumfact/autotune.py index 48b281d1689f2eaff0866438d41a96999170fa2d..4b9a1d132214652a9258cb59b46364117aeece1f 100644 --- a/python/dune/codegen/sumfact/autotune.py +++ b/python/dune/codegen/sumfact/autotune.py @@ -93,7 +93,7 @@ def generate_standalone_code(sf, filename): f.write(" using DF = {};\n".format(real)) from dune.codegen.sumfact.tabulation import name_polynomials - degs = tuple(m.basis_size - 1 for m in sf.matrix_sequence) + degs = tuple(m.basis_size - 1 for m in sf.matrix_sequence_quadrature_permuted) for deg in set(degs): f.write(" Dune::QkStuff::EquidistantLagrangePolynomials<DF, RF, {}> {};\n".format(deg, name_polynomials(deg))) @@ -105,8 +105,8 @@ def generate_standalone_code(sf, filename): constructor_knl = lp.get_one_scheduled_kernel(constructor_knl) # Allocate buffers - size = max(product(m.quadrature_size for m in sf.matrix_sequence) * sf.vector_width, - product(m.basis_size for m in sf.matrix_sequence) * sf.vector_width) + size = max(product(m.quadrature_size for m in sf.matrix_sequence_quadrature_permuted) * sf.vector_width, + product(m.basis_size for m in sf.matrix_sequence_quadrature_permuted) * sf.vector_width) size = int(size * (get_option("precision_bits") / 8)) f.writelines([" char buffer0[{}] __attribute__ ((aligned (32)));\n".format(size), " char buffer1[{}] __attribute__ ((aligned (32)));\n".format(size), diff --git a/python/dune/codegen/sumfact/basis.py b/python/dune/codegen/sumfact/basis.py index d9ecc4a7e6c9a4637526c903ae1c193d38181122..d8194af77400fc26148263d367fde33f25ed2480 100644 --- a/python/dune/codegen/sumfact/basis.py +++ b/python/dune/codegen/sumfact/basis.py @@ -14,8 +14,10 @@ from dune.codegen.generation import (basis_mixin, iname, instruction, kernel_cached, + silenced_warning, temporary_variable, ) +from dune.codegen.loopy.flatten import flatten_index from dune.codegen.loopy.target import type_floatingpoint from dune.codegen.sumfact.tabulation import (basis_functions_per_direction, construct_basis_matrix_sequence, @@ -24,6 +26,11 @@ from dune.codegen.sumfact.tabulation import (basis_functions_per_direction, name_polynomials, polynomial_degree, ) +from dune.codegen.sumfact.permutation import (permute_backward, + permute_forward, + sumfact_cost_permutation_strategy, + sumfact_quadrature_permutation_strategy, + ) from dune.codegen.sumfact.switch import (get_facedir, get_facemod, ) @@ -194,7 +201,8 @@ class SumfactBasisMixin(GenericBasisMixin): facemod=get_facemod(restriction), basis_size=basis_size) - inp = LFSSumfactKernelInput(coeff_func=coeff_func, + inp = LFSSumfactKernelInput(matrix_sequence=matrix_sequence, + coeff_func=coeff_func, element=element, element_index=index, restriction=restriction, @@ -229,16 +237,33 @@ class SumfactBasisMixin(GenericBasisMixin): class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord): def __init__(self, + matrix_sequence=None, coeff_func=None, element=None, element_index=0, restriction=0, ): + + # Note: The function sumfact_quadrature_permutation_strategy does not + # work anymore after the visiting process since get_facedir and + # get_facemod are not well defined. But we need the + # quadrature_permutation to generate the name of the sumfact + # kernel. This means we need to store the value here instead of + # recalculating it in the property. + dim = world_dimension() + quadrature_permutation = sumfact_quadrature_permutation_strategy(dim, restriction) + + matrix_sequence = permute_forward(matrix_sequence, quadrature_permutation) + cost_permutation = sumfact_cost_permutation_strategy(matrix_sequence, self.stage) + + # Note: Do not put matrix_sequence into the Record. That screws up the vectorization strategy! ImmutableRecord.__init__(self, coeff_func=coeff_func, element=element, element_index=element_index, restriction=restriction, + _quadrature_permutation=quadrature_permutation, + _cost_permutation=cost_permutation, ) def __repr__(self): @@ -247,6 +272,27 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord): def __str__(self): return repr(self) + def get_keyword_arguments(self): + """Get dictionary of keyword arguments needed to initialize this class + + Extract keyword arguments from the ImmutableRecord and modify + accordingly. You need to set the correct matrix sequence before using + this dict to create an interface. + """ + dict = self.get_copy_kwargs() + del dict['_cost_permutation'] + del dict['_quadrature_permutation'] + dict['matrix_sequence'] = None + return dict + + @property + def quadrature_permutation(self): + return self._quadrature_permutation + + @property + def cost_permutation(self): + return self._cost_permutation + @property def stage(self): return 1 @@ -255,24 +301,50 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord): def direct_is_possible(self): return get_form_option("fastdg") - def realize(self, sf, insn_dep, index=0): + def setup_input(self, sf, insn_dep, index=0): + """Setup input for a sum factorization kernel function + + Write the coefficients into an array that can be passed to a sum + factorization kernel function (necessary if direct input "fastdg" is + not possible). + + index: Vectorization index + """ + # Inames for interating over the coefficients. We take them from the + # cost permuted matrix sequence. In order to get the inames in order + # x,y,... we need to take the permutation back. + shape_cost_permuted = tuple(mat.basis_size for mat in sf.matrix_sequence_cost_permuted) + shape_ordered = permute_backward(shape_cost_permuted, self.cost_permutation) + shape_ordered = permute_backward(shape_ordered, self.quadrature_permutation) + inames_cost_permuted = tuple(sumfact_iname(length, "setup_inames_" + str(k)) for k, length in enumerate(shape_cost_permuted)) + inames_ordered = permute_backward(inames_cost_permuted, self.cost_permutation) + inames_ordered = permute_backward(inames_ordered, self.quadrature_permutation) + + # The coefficient needs to be accessed with a flat index of inames ordered x,y,... + flat_index = flatten_index(tuple(prim.Variable(i) for i in inames_ordered), + shape_ordered, + order="f") + + # Get the coefficient container lfs = name_lfs(self.element, self.restriction, self.element_index) - basisiname = sumfact_iname(name_lfs_bound(lfs), "basis") container = self.coeff_func(self.restriction) from dune.codegen.pdelab.argument import pymbolic_coefficient as pc - coeff = pc(container, lfs, basisiname) + coeff = pc(container, lfs, flat_index) - # Get the input temporary! + # The array that will be passed to the sum factorization kernel + # function should contain the coefficients in the cost permuted order! from dune.codegen.sumfact.realization import name_buffer_storage name = "input_{}".format(sf.buffer) + ftags = ",".join(["f"] * (sf.length + 1)) temporary_variable(name, - shape=(product(mat.basis_size for mat in sf.permuted_matrix_sequence), sf.vector_width), + shape=(sf.vector_width,) + shape_cost_permuted, custom_base_storage=name_buffer_storage(sf.buffer, 0), managed=True, + dim_tags=ftags, ) - assignee = prim.Subscript(prim.Variable(name), - (prim.Variable(basisiname),) + (index,)) + (index,) + tuple(prim.Variable(i) for i in inames_cost_permuted)) + insn = instruction(assignee=assignee, expression=coeff, depends_on=sf.insn_dep.union(insn_dep), @@ -281,7 +353,35 @@ class LFSSumfactKernelInput(SumfactKernelInterfaceBase, ImmutableRecord): return insn_dep.union(frozenset({insn})) - def realize_direct(self, shape, inames, which=0): + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + # Note: Here we do not need to reverse any permutation since this is + # already done in the setup_input method above! + + # Get a temporary that interprets the base storage of the input + # as a column-major matrix. In later iteration of the matrix loop + # this reinterprets the output of the previous iteration. + inp = buf.get_temporary("buff_step0_in", + shape=shape + vec_shape, + dim_tags=ftags, + ) + + # The input temporary will only be read from, so we need to silence + # the loopy warning + silenced_warning('read_no_write({})'.format(inp)) + + return prim.Subscript(prim.Variable(inp), inames + vec_iname) + + def realize_direct_input(self, inames, shape, which=0): + # If the input comes directly from a global data structure inames are + # ordered x,y,z,... + # + # The inames and shape passed to this method come from the cost + # permuted matrix sequence so we need to permute them back + shape = permute_backward(shape, self.cost_permutation) + shape = permute_backward(shape, self.quadrature_permutation) + inames = permute_backward(inames, self.cost_permutation) + inames = permute_backward(inames, self.quadrature_permutation) + arg = "fastdg{}".format(which) from dune.codegen.sumfact.accumulation import _dof_offset diff --git a/python/dune/codegen/sumfact/geometry.py b/python/dune/codegen/sumfact/geometry.py index feda608341ec4d82d93a5c749372fb5a97983a89..102df6ee2b91c8896096830ab0d862e608c16e39 100644 --- a/python/dune/codegen/sumfact/geometry.py +++ b/python/dune/codegen/sumfact/geometry.py @@ -15,6 +15,7 @@ from dune.codegen.generation import (class_member, globalarg, valuearg, ) +from dune.codegen.loopy.flatten import flatten_index from dune.codegen.options import get_option from dune.codegen.pdelab.geometry import (enforce_boundary_restriction, local_dimension, @@ -30,11 +31,20 @@ from dune.codegen.pdelab.localoperator import (name_ansatz_gfs_constructor_param lop_template_range_field, ) from dune.codegen.pdelab.restriction import restricted_name -from dune.codegen.sumfact.accumulation import basis_sf_kernels +from dune.codegen.sumfact.accumulation import basis_sf_kernels, sumfact_iname from dune.codegen.sumfact.basis import construct_basis_matrix_sequence +from dune.codegen.sumfact.permutation import (permute_backward, + permute_forward, + sumfact_cost_permutation_strategy, + sumfact_quadrature_permutation_strategy, + ) from dune.codegen.sumfact.quadrature import additional_inames +from dune.codegen.sumfact.realization import (name_buffer_storage, + realize_sum_factorization_kernel, + ) from dune.codegen.sumfact.switch import get_facedir, get_facemod from dune.codegen.sumfact.symbolic import SumfactKernelInterfaceBase, SumfactKernel +from dune.codegen.sumfact.vectorization import attach_vectorization_info from dune.codegen.tools import get_pymbolic_basename from dune.codegen.options import get_form_option, option_switch from dune.codegen.ufl.modified_terminals import Restriction @@ -206,7 +216,10 @@ class SumfactMultiLinearGeometryMixin(GenericPDELabGeometryMixin): matrix_sequence = construct_basis_matrix_sequence(facedir=get_facedir(restriction), facemod=get_facemod(restriction), basis_size=(2,) * world_dimension()) - inp = GeoCornersInput(self.indices[0], restriction) + inp = GeoCornersInput(matrix_sequence=matrix_sequence, + direction=self.indices[0], + restriction=restriction, + ) sf = SumfactKernel(matrix_sequence=matrix_sequence, interface=inp, ) @@ -320,7 +333,10 @@ def global_corner_iname(restriction): class GeoCornersInput(SumfactKernelInterfaceBase, ImmutableRecord): - def __init__(self, direction, restriction): + def __init__(self, + matrix_sequence=None, + direction=None, + restriction=None): """Base class for sum-factorized evaluation of geometry mappings At the moment we only do this for cells and not faces. For @@ -331,7 +347,26 @@ class GeoCornersInput(SumfactKernelInterfaceBase, ImmutableRecord): argument 'direction' specifies the component (x-component: 0, y-component: 1, z-component: 2). """ - ImmutableRecord.__init__(self, direction=direction, restriction=restriction) + + # Note: The function sumfact_quadrature_permutation_strategy does not + # work anymore after the visiting process since get_facedir and + # get_facemod are not well defined. But we need the + # quadrature_permutation to generate the name of the sumfact + # kernel. This means we need to store the value here instead of + # recalculating it in the property. + dim = world_dimension() + quadrature_permutation = sumfact_quadrature_permutation_strategy(dim, restriction) + + matrix_sequence = permute_forward(matrix_sequence, quadrature_permutation) + cost_permutation = sumfact_cost_permutation_strategy(matrix_sequence, self.stage) + + # Note: Do not put matrix_sequence into the Record. That screws up the vectorization strategy! + ImmutableRecord.__init__(self, + direction=direction, + restriction=restriction, + _quadrature_permutation=quadrature_permutation, + _cost_permutation=cost_permutation, + ) def __repr__(self): return ImmutableRecord.__repr__(self) @@ -339,6 +374,27 @@ class GeoCornersInput(SumfactKernelInterfaceBase, ImmutableRecord): def __str__(self): return repr(self) + def get_keyword_arguments(self): + """Get dictionary of keyword arguments needed to initialize this class + + Extract keyword arguments from the ImmutableRecord and modify + accordingly. You need to set the correct matrix sequence before using + this dict to create an interface. + """ + dict = self.get_copy_kwargs() + del dict['_cost_permutation'] + del dict['_quadrature_permutation'] + dict['matrix_sequence'] = None + return dict + + @property + def quadrature_permutation(self): + return self._quadrature_permutation + + @property + def cost_permutation(self): + return self._cost_permutation + @property def stage(self): return 1 @@ -347,16 +403,36 @@ class GeoCornersInput(SumfactKernelInterfaceBase, ImmutableRecord): def direct_is_possible(self): return False - def realize(self, sf, insn_dep, index=0): - # Note: world_dimension, since we only do evaluation of cell geometry mappings - from dune.codegen.sumfact.realization import name_buffer_storage + def setup_input(self, sf, insn_dep, index=0): + # Inames for interating over the coefficients (in this case the + # coordinate of the component 'sefl.direction' of the corners). We take + # them from the cost permuted matrix sequence. In order to get the + # inames in order x,y,... we need to take the permutation back. + shape_cost_permuted = tuple(mat.basis_size for mat in sf.matrix_sequence_cost_permuted) + shape_ordered = permute_backward(shape_cost_permuted, self.cost_permutation) + shape_ordered = permute_backward(shape_ordered, self.quadrature_permutation) + inames_cost_permuted = tuple(sumfact_iname(length, "corner_setup_inames_" + str(k)) for k, length in enumerate(shape_cost_permuted)) + inames_ordered = permute_backward(inames_cost_permuted, self.cost_permutation) + inames_ordered = permute_backward(inames_ordered, self.quadrature_permutation) + + # Flat indices needed to access pdelab corner method + flat_index_ordered = flatten_index(tuple(prim.Variable(i) for i in inames_ordered), + shape_ordered, + order="f") + flat_index_cost_permuted = flatten_index(tuple(prim.Variable(i) for i in inames_cost_permuted), + shape_cost_permuted, + order="f") + + # The array that will be passed to the sum factorization kernel + # function should contain the coefficients in the cost permuted order! name = "input_{}".format(sf.buffer) + ftags = ",".join(["f"] * (sf.length + 1)) temporary_variable(name, - shape=(2 ** world_dimension(), sf.vector_width), + shape=(sf.vector_width,) + shape_cost_permuted, custom_base_storage=name_buffer_storage(sf.buffer, 0), managed=True, + dim_tags=ftags, ) - ciname = global_corner_iname(self.restriction) if self.restriction == 0: geo = name_geometry() @@ -367,23 +443,38 @@ class GeoCornersInput(SumfactKernelInterfaceBase, ImmutableRecord): # method does return a non-scalar, which does not fit into the current # loopy philosophy for function calls. This problem will be solved once # #11 is resolved. Admittedly, the code looks *really* ugly until that happens. - code = "{}[{}*{}+{}] = {}.corner({})[{}];".format(name, - sf.vector_width, - ciname, - index, - geo, - ciname, - self.direction, - ) + code = "{}[{}*({})+{}] = {}.corner({})[{}];".format(name, + sf.vector_width, + str(flat_index_cost_permuted), + index, + geo, + str(flat_index_ordered), + self.direction, + ) insn = instruction(code=code, - within_inames=frozenset({ciname}), + within_inames=frozenset(inames_cost_permuted), assignees=(name,), tags=frozenset({"sumfact_stage{}".format(sf.stage)}), ) return insn_dep.union(frozenset({insn})) + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + # Get a temporary that interprets the base storage of the input + # as a column-major matrix. In later iteration of the matrix loop + # this reinterprets the output of the previous iteration. + inp = buf.get_temporary("buff_step0_in", + shape=shape + vec_shape, + dim_tags=ftags, + ) + + # The input temporary will only be read from, so we need to silence + # the loopy warning + silenced_warning('read_no_write({})'.format(inp)) + + return prim.Subscript(prim.Variable(inp), inames + vec_iname) + @preamble def define_corner(name, low): @@ -446,13 +537,12 @@ def _name_jacobian(i, j, restriction, visitor): basis_size=(2,) * world_dimension()) # Sum factorization input for the i'th component of the geometry mapping - inp = GeoCornersInput(i, restriction) - + inp = GeoCornersInput(matrix_sequence=matrix_sequence, + direction=i, + restriction=restriction) sf = SumfactKernel(matrix_sequence=matrix_sequence, interface=inp, ) - - from dune.codegen.sumfact.vectorization import attach_vectorization_info vsf = attach_vectorization_info(sf) # If this sum factorization kernel was not used in the dry run we @@ -463,7 +553,6 @@ def _name_jacobian(i, j, restriction, visitor): # Add a sum factorization kernel that implements the evaluation of # the basis functions at quadrature points (stage 1) - from dune.codegen.sumfact.realization import realize_sum_factorization_kernel var, _ = realize_sum_factorization_kernel(vsf) assert(visitor.indices is None) diff --git a/python/dune/codegen/sumfact/permutation.py b/python/dune/codegen/sumfact/permutation.py index 79b758fcae2252d879cb28e2ca3c87de10019a1d..7f37dfeae795031ec81b292b96e65649f8fc78cc 100644 --- a/python/dune/codegen/sumfact/permutation.py +++ b/python/dune/codegen/sumfact/permutation.py @@ -4,6 +4,7 @@ import itertools from dune.codegen.options import get_option from dune.codegen.sumfact.switch import get_facedir, get_facemod +from dune.codegen.ufl.modified_terminals import Restriction def sumfact_permutation_heuristic(permutations, stage): @@ -45,16 +46,12 @@ def flop_cost(matrix_sequence): return 2 * cost -def sumfact_permutation_strategy(sf): +def sumfact_cost_permutation_strategy(matrix_sequence, stage): """Choose permutation of the matrix sequence based on computational cost Note: If there are multiple permutations with the same cost a heuristic is used to pick one. """ - # Extract information from the SumfactKernel object - matrix_sequence = sf.permuted_matrix_sequence - stage = sf.stage - # Combine permutation and matrix_sequence perm = [i for i, _ in enumerate(matrix_sequence)] perm_matrix_sequence = zip(perm, matrix_sequence) @@ -120,26 +117,37 @@ def sumfact_quadrature_permutation_strategy(dim, restriction): # Use a simpler convention for structured grids. In this case we can always # go through the directions in the normal order. The same is true for 2D # and sum factorization on volumes. - if (not get_option('grid_unstructured')) or dim == 2 or restriction == 0: + if (not get_option('grid_unstructured')) or dim == 2 or restriction == Restriction.NONE: return tuple(range(dim)) else: + # Draw a cube with edge orientations. We always do the normal direction + # first. The first case for facedir=0, facemod=0 was chosen that way, + # all others can be derived by rotating the cube and matching edge + # directions. def _order_on_self(restriction): facedir = get_facedir(restriction) facemod = get_facemod(restriction) - # Here we specify the convention - if (facedir, facemod) in [(0, 0), (1, 1), (2, 0)]: - return tuple(range(dim)) - else: - l = list(range(dim)) - l.reverse() - return tuple(l) - - # On neighbor we need the reverse order - if restriction == 1: + quadrature_order = { + (0, 0): (0, 1, 2), + (0, 1): (0, 2, 1), + (1, 0): (1, 2, 0), + (1, 1): (1, 0, 2), + (2, 0): (2, 0, 1), + (2, 1): (2, 1, 0), + } + + return quadrature_order[(facedir, facemod)] + + # On neighbor we also do the normal direction first. The other two can + # be derived by putting a second edge oriented cube besides the first + # one. Then rotate and match edge directions. + if restriction == Restriction.POSITIVE: return _order_on_self(restriction) else: - assert restriction == 2 + # Still do normal direction first. The other two directions need to + # be done in reverse order to go through the quadrature points in + # the same order as on self (draw cubes!). + assert restriction == Restriction.NEGATIVE l = list(_order_on_self(restriction)) - l.reverse() - return tuple(l) + return (l[0], l[2], l[1]) diff --git a/python/dune/codegen/sumfact/realization.py b/python/dune/codegen/sumfact/realization.py index a40be948fb8d36969c83672c1f9102eaedf5282d..8b585d4ce9a91c8565cb9e6b2b9b495b3734b2e6 100644 --- a/python/dune/codegen/sumfact/realization.py +++ b/python/dune/codegen/sumfact/realization.py @@ -23,8 +23,7 @@ from dune.codegen.options import (get_form_option, get_option, ) from dune.codegen.pdelab.signatures import assembler_routine_name -from dune.codegen.sumfact.permutation import (sumfact_permutation_strategy, - permute_backward, +from dune.codegen.sumfact.permutation import (permute_backward, permute_forward, ) from dune.codegen.sumfact.quadrature import quadrature_points_per_direction @@ -75,8 +74,8 @@ def _realize_sum_factorization_kernel(sf): for buf in buffers: # Determine the necessary size of the buffer. We assume that we do not # underintegrate the form!!! - size = max(product(m.quadrature_size for m in sf.permuted_matrix_sequence) * sf.vector_width, - product(m.basis_size for m in sf.permuted_matrix_sequence) * sf.vector_width) + size = max(product(m.quadrature_size for m in sf.matrix_sequence_cost_permuted) * sf.vector_width, + product(m.basis_size for m in sf.matrix_sequence_cost_permuted) * sf.vector_width) temporary_variable("{}_dummy".format(buf), shape=(size,), custom_base_storage=buf, @@ -85,7 +84,7 @@ def _realize_sum_factorization_kernel(sf): # Realize the input if it is not direct if sf.stage == 1 and not sf.interface.direct_is_possible: - insn_dep = insn_dep.union(sf.interface.realize(sf, insn_dep)) + insn_dep = insn_dep.union(sf.interface.setup_input(sf, insn_dep)) # Trigger generation of the sum factorization kernel function qp = quadrature_points_per_direction() @@ -153,24 +152,19 @@ def realize_sumfact_kernel_function(sf): ctags = ctags + ",vec" vec_shape = (sf.vector_width,) - # Decide in which order we want to process directions in the - # sumfactorization. A clever ordering can lead to a reduced - # complexity. This will e.g. happen at faces where we only have - # one quadratue point m_l=1 if l is the normal direction of the - # face. - # - # Rule of thumb: small m's early and large n's late. - perm = sumfact_permutation_strategy(sf) - - # Permute matrix sequence - matrix_sequence = permute_forward(sf.permuted_matrix_sequence, perm) + # Matrix sequence of this sum factorization kernel + matrix_sequence = sf.matrix_sequence_cost_permuted # Product of all matrices for l, matrix in enumerate(matrix_sequence): # Compute the correct shapes of in- and output matrices of this matrix-matrix multiplication # and get inames that realize the product. - inp_shape = (matrix.cols,) + tuple(mat.cols for mat in matrix_sequence[l + 1:]) + tuple(mat.rows for mat in matrix_sequence[:l]) - out_shape = (matrix.rows,) + tuple(mat.cols for mat in matrix_sequence[l + 1:]) + tuple(mat.rows for mat in matrix_sequence[:l]) + inp_shape = (matrix.cols,) \ + + tuple(mat.cols for mat in matrix_sequence[l + 1:]) \ + + tuple(mat.rows for mat in matrix_sequence[:l]) + out_shape = (matrix.rows,) \ + + tuple(mat.cols for mat in matrix_sequence[l + 1:]) \ + + tuple(mat.rows for mat in matrix_sequence[:l]) out_inames = tuple(sumfact_iname(length, "out_inames_" + str(k)) for k, length in enumerate(out_shape)) vec_iname = () if matrix.vectorized: @@ -182,11 +176,11 @@ def realize_sumfact_kernel_function(sf): # a code generation corner case producing way too complicated code. This # could be fixed upstream, but the loopy code realizing reductions is not # trivial and the priority is kind of low. - if matrix.cols != 1: + if matrix.cols == 1: + k_expr = 0 + else: k = sumfact_iname(matrix.cols, "red") k_expr = prim.Variable(k) - else: - k_expr = 0 # Setup the input of the sum factorization kernel. In the # first matrix multiplication this can be taken from @@ -195,32 +189,18 @@ def realize_sumfact_kernel_function(sf): # * a value from a global data structure, broadcasted to a vector type # (vectorized + FastDGGridOperator) input_inames = (k_expr,) + tuple(prim.Variable(j) for j in out_inames[1:]) - if l == 0 and sf.stage == 1 and sf.interface.direct_is_possible: - # One permutation for cost reduction, see comment below - inp_shape = permute_backward(inp_shape, perm) - input_inames = permute_backward(input_inames, perm) - - # And one more for permuted quadrature points, see comment below - inp_shape = permute_backward(inp_shape, sf.quadrature_permutation) - input_inames = permute_backward(input_inames, sf.quadrature_permutation) - input_summand = sf.interface.realize_direct(inp_shape, input_inames) + if l == 0 and sf.stage == 1 and sf.interface.direct_is_possible: + input_summand = sf.interface.realize_direct_input(input_inames, inp_shape) + elif l == 0: + input_summand = sf.interface.realize_input(input_inames, + inp_shape, + vec_iname, + vec_shape, + buffer, + ftags, + ) else: - # If we did permute the order of a matrices above we also - # permuted the order of out_inames. Unfortunately the - # order of our input is from 0 to d-1. This means we need - # to permute _back_ to get the right coefficients. - if l == 0: - inp_shape = permute_backward(inp_shape, perm) - input_inames = permute_backward(input_inames, perm) - if sf.stage == 1: - # In the unstructured case the sf.permuted_matrix_sequence could - # already be permuted according to - # sf.quadrature_permutation. We also need to reverse this - # permutation to get the input from 0 to d-1. - inp_shape = permute_backward(inp_shape, sf.quadrature_permutation) - input_inames = permute_backward(input_inames, sf.quadrature_permutation) - # Get a temporary that interprets the base storage of the input # as a column-major matrix. In later iteration of the matrix loop # this reinterprets the output of the previous iteration. @@ -238,26 +218,6 @@ def realize_sumfact_kernel_function(sf): buffer.switch() - # Get a temporary that interprets the base storage of the output. - # - # Note: In this step the reordering of the fastest directions - # is happening. The new direction (out_inames[0]) and the - # corresponding shape (out_shape[0]) goes to the end (slowest - # direction) and everything stays column major (ftags->fortran - # style). - # - # If we are in the last step we reverse the permutation. - output_shape = tuple(out_shape[1:]) + (out_shape[0],) - if l == len(matrix_sequence) - 1: - output_shape = permute_backward(output_shape, perm) - if sf.stage == 3: - output_shape = permute_backward(output_shape, sf.quadrature_permutation) - - out = buffer.get_temporary("buff_step{}_out".format(l), - shape=output_shape + vec_shape, - dim_tags=ftags, - ) - # Write the matrix-matrix multiplication expression matprod = prim.Product((matrix.pymbolic((prim.Variable(out_inames[0]), k_expr) + vec_iname), input_summand)) @@ -266,13 +226,8 @@ def realize_sumfact_kernel_function(sf): if matrix.cols != 1: matprod = lp.Reduction("sum", k, matprod) - # Here we also move the new direction (out_inames[0]) to the - # end and reverse permutation + # Here we also move the new direction (out_inames[0]) to the end output_inames = tuple(prim.Variable(i) for i in out_inames[1:]) + (prim.Variable(out_inames[0]),) - if l == len(matrix_sequence) - 1: - output_inames = permute_backward(output_inames, perm) - if sf.stage == 3: - output_inames = permute_backward(output_inames, sf.quadrature_permutation) # Collect the key word arguments for the loopy instruction insn_args = {"depends_on": insn_dep} @@ -282,8 +237,39 @@ def realize_sumfact_kernel_function(sf): if l == len(matrix_sequence) - 1 and get_form_option('fastdg') and sf.stage == 3: if sf.vectorized: insn_args["forced_iname_deps"] = frozenset({vec_iname[0].name}) - insn_dep = sf.interface.realize_direct(matprod, output_inames, out_shape, **insn_args) + insn_dep = sf.interface.realize_direct_output(matprod, output_inames, out_shape, **insn_args) + elif l == len(matrix_sequence) - 1: + # Handle output of the last tensor contraction + # + # Stage 1: Reverse cost permutation, keep quadrature permutation + # Stage 3: Reverse cost and quadrature permuation + output_shape = tuple(out_shape[1:]) + (out_shape[0],) + output_inames = permute_backward(output_inames, sf.interface.cost_permutation) + output_shape = permute_backward(output_shape, sf.interface.cost_permutation) + if sf.interface.stage == 3: + output_inames = permute_backward(output_inames, sf.interface.quadrature_permutation) + output_shape = permute_backward(output_shape, sf.interface.quadrature_permutation) + + out = buffer.get_temporary("buff_step{}_out".format(l), + shape=output_shape + vec_shape, + dim_tags=ftags, + ) + + # Issue the reduction instruction that implements the multiplication + # at the same time store the instruction ID for the next instruction to depend on + insn_dep = frozenset({instruction(assignee=prim.Subscript(prim.Variable(out), output_inames + vec_iname), + expression=matprod, + **insn_args, + ) + }) + else: + output_shape = tuple(out_shape[1:]) + (out_shape[0],) + out = buffer.get_temporary("buff_step{}_out".format(l), + shape=output_shape + vec_shape, + dim_tags=ftags, + ) + # Issue the reduction instruction that implements the multiplication # at the same time store the instruction ID for the next instruction to depend on insn_dep = frozenset({instruction(assignee=prim.Subscript(prim.Variable(out), output_inames + vec_iname), diff --git a/python/dune/codegen/sumfact/symbolic.py b/python/dune/codegen/sumfact/symbolic.py index 05dc74b12b296f6f627aea56a3832110c292ddd2..da128f82ea4385804c4cdfab785ad7acf7c5fc4a 100644 --- a/python/dune/codegen/sumfact/symbolic.py +++ b/python/dune/codegen/sumfact/symbolic.py @@ -2,11 +2,18 @@ from dune.codegen.options import get_form_option, get_option from dune.codegen.generation import (get_counted_variable, + instruction, + silenced_warning, subst_rule, transform, ) from dune.codegen.pdelab.geometry import local_dimension, world_dimension -from dune.codegen.sumfact.permutation import permute_forward, sumfact_quadrature_permutation_strategy +from dune.codegen.sumfact.permutation import (flop_cost, + permute_backward, + permute_forward, + sumfact_cost_permutation_strategy, + sumfact_quadrature_permutation_strategy, + ) from dune.codegen.sumfact.tabulation import BasisTabulationMatrixBase, BasisTabulationMatrixArray from dune.codegen.loopy.target import dtype_floatingpoint, type_floatingpoint from dune.codegen.loopy.vcl import ExplicitVCLCast, VCLLowerUpperLoad @@ -23,15 +30,166 @@ import inspect class SumfactKernelInterfaceBase(object): - """ A base class for the input/output of a sum factorization kernel + """A base class for the input/output of a sum factorization kernel In stage 1, this represents the input object, in stage 3 the output object. + + Notes about permutations: + - setup_input: handle cost and quadrature permutation + - realize_input stage 1: no permutations + - realize_input stage 3: only cost permutation + - realize_direct_input: cost and quadrature permutation + - accumulate_output: no permutation + - realize_direct_output: cost and quadrature permutation + + In the vectorized case most permutation handling is forwarded to the scalar + kernels. """ - def realize(self, *a, **kw): + def setup_input(self, sf, insn_dep, index=0): + """Create and fill an input array for a stage 1 sumfact kernel function (non fastdg) + + This happens before the function call. The input will be quadrature + (for unstructured grids) and cost permuted. + + Parameters + ---------- + sf : SumfactKernel or VectorizedSumfactKernel + insn_dep : frozenset + Instructions this setup depends on. + index : int + Vectorization index, SIMD lane. + """ + raise NotImplementedError + + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + """Interpret the input of sumfact kernel function in the right way (non fastdgg) + + This happens inside the sumfact kernel function. + + Stage 1 : Input is already permuted the right way in setup_input. + + Stage 3 : The inames are cost and quadrature permuted but the input is + only quadrature permuted. This means we need to reverse the cost + permutation on the inames. + + Parameters + ---------- + inames : tuple of pymbolic.primitives.Variable + Inames for accesing the input. Ordered according to permuted matrix sequence. + shape : tuple of int + Shape of input. Ordered according to permuted matrix sequence. + vec_iname : tuple of pymbolic.primitives.Variable + In case of vectorized kernel provide vectorization iname. + vec_shape : tuple of int + In case of vectorized kernel provide the number of vectorized kernels. + buf : dune.codegen.sumfact.realization.BufferSwitcher + Provides the input variable. + ftags : str + dim_tags needed to access input variable correctly. + """ + raise NotImplementedError + + def realize_direct_input(self, inames, shape, which=0): + """Interpret the input of sumfact kernel function in the right way (fastdg) + + This happens inside the sumfact kernel function. + + Stage 1: The input to the sum factorization kernel will be ordered x, + y, z,... The shape and inames from this method come from the cost + permuted matrix sequence. Make sure to permute them back when accesing + the input. + + Parameters + ---------- + inames : tuple of pymbolic.primitives.Variable + Inames for accesing the input. Ordered according to permuted matrix sequence. + shape: tuple of int + Shape of input. Ordered according to permuted matrix sequence. + which : int + In case of VetcorizedSumfactKernel this might specify if the lower or upper + part of a the SIMD register is for this input. + """ + raise NotImplementedError + + def accumulate_output(self, sf, result, insn_dep, inames=None, additional_inames=()): + """Generate accumulate instruction after a stage 3 sumfact kernel function (non fastdg) + + This happens after the function call. After stage 3 the result should + be ordered x, y, z,..., no permutations necessary. + + Parameters + ---------- + sf : SumfactKernel or VectorizedSumfactKernel + result : SumfactKernel or some pymbolic stuff + Result of a sum factorization + insn_dep : frozenset + Instructions this setup depends on. + inames : tuple of pymbolic.primitives.Variable + additional_inames : tuple of pymbolic.primitives.Variable + Additional inames the accumulation instruction depends on (eg. loop over + ansatz functions for jacobians). + """ + raise NotImplementedError + + def realize_direct_output(self, result, iname, shape, which=0, **kwargs): + """Accumulate results directly in the sumfact kernel function (fastdg) + + This happens inside the sumfact kernel function. + + Needs to handle cost and quadrature permutation. + + Parameters + ---------- + result : pymbolic stuff + Result of the sum factorization + iname : tuple of pymbolic.primitives.Variable + shape : tuple of ints + which : int + TODO Doc me! + **kwargs : + Key word arguments passed to loopy instruction + """ + raise NotImplementedError + + @property + def quadrature_permutation(self): + """Order of local coordinate axis + + On unstructured grids we sometimes need to go through the directions in + different order to make sure that we visit the (global) quadrature + points on self and neighbor in the same order. + """ raise NotImplementedError - def realize_direct(self, *a, **kw): + @property + def cost_permutation(self): + """Permutation that minimizes flops + """ raise NotImplementedError + @property + def combined_permutation(self): + return permute_forward(self.quadrature_permutation, self.cost_permutation) + + def permute_backward_cost(self, shape, inames): + shape = permute_backward(shape, self.cost_permutation) + inames = permute_backward(inames, self.cost_permutation) + return shape, inames + + def permute_backward_quadrature(self, shape, inames): + shape = permute_backward(shape, self.quadrature_permutation) + inames = permute_backward(inames, self.quadrature_permutation) + return shape, inames + + def permute_forward_cost(self, shape, inames): + shape = permute_forward(shape, self.cost_permutation) + inames = permute_forward(inames, self.cost_permutation) + return shape, inames + + def permute_forward_quadrature(self, shape, inames): + shape = permute_forward(shape, self.quadrature_permutation) + inames = permute_forward(inames, self.quadrature_permutation) + return shape, inames + @property def within_inames(self): return () @@ -68,6 +226,24 @@ class VectorSumfactKernelInput(SumfactKernelInterfaceBase): def __repr__(self): return "_".join(repr(i) for i in self.interfaces) + @property + def quadrature_permutation(self): + # TODO: For now we only vectorize sumfact kernels with the same + # quadrature permutation. This should be extended. + for i in self.interfaces: + assert i.quadrature_permutation == self.interfaces[0].quadrature_permutation + return self.interfaces[0].quadrature_permutation + + @property + def cost_permutation(self): + # This should hold true due to the choice of quadrature + # permutation. For both structured and unstructured grids the order of + # the global directions should be the same leading to the same cost + # permutation for all those sum factorization kernels. + for i in self.interfaces: + assert i.cost_permutation == self.interfaces[0].cost_permutation + return self.interfaces[0].cost_permutation + @property def stage(self): return 1 @@ -76,12 +252,27 @@ class VectorSumfactKernelInput(SumfactKernelInterfaceBase): def direct_is_possible(self): return all(i.direct_is_possible for i in self.interfaces) - def realize(self, sf, dep): + def setup_input(self, sf, dep): for i, inp in enumerate(self.interfaces): - dep = dep.union(inp.realize(sf, dep, index=i)) + dep = dep.union(inp.setup_input(sf, dep, index=i)) return dep - def realize_direct(self, shape, inames): + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + # Get a temporary that interprets the base storage of the input + # as a column-major matrix. In later iteration of the matrix loop + # this reinterprets the output of the previous iteration. + inp = buf.get_temporary("buff_step0_in", + shape=shape + vec_shape, + dim_tags=ftags, + ) + + # The input temporary will only be read from, so we need to silence + # the loopy warning + silenced_warning('read_no_write({})'.format(inp)) + + return prim.Subscript(prim.Variable(inp), inames + vec_iname) + + def realize_direct_input(self, inames, shape): # Check whether the input exhibits a favorable structure # (whether we can broadcast scalar values into SIMD registers) total = set(self.interfaces) @@ -92,15 +283,15 @@ class VectorSumfactKernelInput(SumfactKernelInterfaceBase): # All input coefficients use the exact same input coefficient. # We implement this by broadcasting it into a SIMD register return prim.Call(ExplicitVCLCast(dtype_floatingpoint()), - (self.interfaces[0].realize_direct(shape, inames),) + (self.interfaces[0].realize_direct_input(inames, shape),) ) elif len(total) == 2 and len(lower) == 1 and len(upper) == 1: # The lower and the upper part of the SIMD register use # the same input coefficient, we combine the SIMD register # from two shorter SIMD types return prim.Call(VCLLowerUpperLoad(dtype_floatingpoint()), - (self.interfaces[0].realize_direct(shape, inames), - self.interfaces[len(self.interfaces) // 2].realize_direct(shape, inames, which=1), + (self.interfaces[0].realize_direct_input(inames, shape), + self.interfaces[len(self.interfaces) // 2].realize_direct_input(inames, shape, which=1), ) ) else: @@ -114,7 +305,7 @@ class VectorSumfactKernelInput(SumfactKernelInterfaceBase): @property def signature_args(self): - if get_form_option("fastdg"): + if self.interfaces[0].direct_is_possible: return tuple("const {}* fastdg{}".format(type_floatingpoint(), i) for i, _ in enumerate(remove_duplicates(self.interfaces))) else: return () @@ -135,6 +326,24 @@ class VectorSumfactKernelOutput(SumfactKernelInterfaceBase): def __repr__(self): return "_".join(repr(o) for o in self.interfaces) + @property + def cost_permutation(self): + # This should hold true due to the choice of quadrature + # permutation. For both structured and unstructured grids the order of + # the global directions should be the same leading to the same cost + # permutation for all those sum factorization kernels. + for i in self.interfaces: + assert i.cost_permutation == self.interfaces[0].cost_permutation + return self.interfaces[0].cost_permutation + + @property + def quadrature_permutation(self): + # TODO: For now we only vectorize sumfact kernels with the same + # quadrature permutation. This should be extended . + for i in self.interfaces: + assert i.quadrature_permutation == self.interfaces[0].quadrature_permutation + return self.interfaces[0].quadrature_permutation + @property def stage(self): return 3 @@ -154,26 +363,28 @@ class VectorSumfactKernelOutput(SumfactKernelInterfaceBase): return prim.Call(prim.Variable(hadd_function), (result,)) - def realize(self, sf, result, insn_dep): - outputs = set(self.interfaces) + def realize_input(self, inames, shape, vec_iname, vec_shape, buf, ftags): + # The input for stage 3 is quadrature permuted. The inames and shape + # passed to this method are quadrature and cost permuted. This means we + # need to take the cost permutation back to get the right inames and + # shape for interpreting the input! + shape = permute_backward(shape, self.cost_permutation) + inames = permute_backward(inames, self.cost_permutation) - trial_element, = set(o.trial_element for o in self.interfaces) - trial_element_index = set(o.trial_element_index for o in self.interfaces).pop() - from dune.codegen.sumfact.accumulation import accum_iname - element = get_leaf(trial_element, trial_element_index) if trial_element is not None else None - inames = tuple(accum_iname(element, mat.rows, i) - for i, mat in enumerate(sf.permuted_matrix_sequence)) - veciname = accum_iname(element, sf.vector_width // len(outputs), "vec") - transform(lp.tag_inames, [(veciname, "vec")]) + # Get a temporary that interprets the base storage of the input as a + # column-major matrix. + inp = buf.get_temporary("buff_step0_in", + shape=shape + vec_shape, + dim_tags=ftags, + ) - deps = frozenset() - for o in outputs: - hadd_result = self._add_hadd(o, maybe_wrap_subscript(result, tuple(prim.Variable(iname) for iname in inames + (veciname,)))) - deps = deps.union(o.realize(sf, hadd_result, insn_dep, inames=inames, additional_inames=(veciname,))) + # The input temporary will only be read from, so we need to silence + # the loopy warning + silenced_warning('read_no_write({})'.format(inp)) - return deps + return prim.Subscript(prim.Variable(inp), inames + vec_iname) - def realize_direct(self, result, inames, shape, **args): + def realize_direct_output(self, result, inames, shape, **args): outputs = set(self.interfaces) # If multiple horizontal_add's are to be performed with 'result' @@ -188,7 +399,42 @@ class VectorSumfactKernelOutput(SumfactKernelInterfaceBase): for o in outputs: hadd_result = self._add_hadd(o, result) which = tuple(remove_duplicates(self.interfaces)).index(o) - deps = deps.union(o.realize_direct(hadd_result, inames, shape, which=which, **args)) + deps = deps.union(o.realize_direct_output(hadd_result, + inames, + shape, + which=which, + **args)) + + return deps + + def accumulate_output(self, sf, result, insn_dep): + outputs = set(self.interfaces) + + # Note: Using matrix_sequence_quadrature_permuted is ok in this place since: + # + # - If the grid is unstructured we assume that the polynomial degree + # for each direction is the same. + # + # - If the grid is structured the quadrature permuted matrix sequence + # is the same as the original one. We still need to call this one + # since VectorizedSumfactKernels do not have the matrix_sequence + # attribute. + basis_size = tuple(mat.basis_size for mat in sf.matrix_sequence_quadrature_permuted) + if get_option('grid_unstructured'): + assert len(set(basis_size)) == 1 + + trial_element, = set(o.trial_element for o in self.interfaces) + trial_element_index = set(o.trial_element_index for o in self.interfaces).pop() + from dune.codegen.sumfact.accumulation import accum_iname + element = get_leaf(trial_element, trial_element_index) if trial_element is not None else None + inames = tuple(accum_iname(element, size, i) for i, size in enumerate(basis_size)) + veciname = accum_iname(element, sf.vector_width // len(outputs), "vec") + transform(lp.tag_inames, [(veciname, "vec")]) + + deps = frozenset() + for o in outputs: + hadd_result = self._add_hadd(o, maybe_wrap_subscript(result, tuple(prim.Variable(iname) for iname in inames + (veciname,)))) + deps = deps.union(o.accumulate_output(sf, hadd_result, insn_dep, inames=inames, additional_inames=(veciname,))) return deps @@ -232,7 +478,6 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): insn_dep=frozenset(), interface=SumfactKernelInterfaceBase(), predicates=frozenset(), - quadrature_permutation=None, ): """Create a sum factorization kernel @@ -306,27 +551,12 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): for a in SumfactKernel.init_arg_names: defaultdict[a] = eval(a) - dim = len(matrix_sequence) - # Not sure if this whole permuting would make sense if we would do sum # factorized evaluation of intersections where len(matrix_sequence) # would not be equal to world dim. + dim = len(matrix_sequence) assert dim == world_dimension() - # Get restriction for this sum factorization kernel. Note: For - # accumulation output we have a restriction for the test (index 0) and - # ansatz (index 1) space. We need the restriction corresponding to the - # test space since we are in stage 3 - restriction = interface.restriction - if isinstance(restriction, tuple): - assert interface.stage is 3 - assert len(restriction) is 2 - restriction = restriction[0] - - # Store correct quadrature_permutation - quadrature_permuation = sumfact_quadrature_permutation_strategy(dim, restriction) - defaultdict['quadrature_permutation'] = quadrature_permuation - # Call the base class constructors ImmutableRecord.__init__(self, **defaultdict) prim.Variable.__init__(self, "SUMFACT") @@ -343,10 +573,10 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): return lp.symbolic.StringifyMapper def __str__(self): - # Return permuted_matrix_sequence + # Return matrix_sequence_quadrature_permuted return "SF{}:[{}]->[{}]".format(self.stage, str(self.interface), - ", ".join(str(m) for m in self.permuted_matrix_sequence)) + ", ".join(str(m) for m in self.matrix_sequence_quadrature_permuted)) mapper_method = "map_sumfact_kernel" @@ -357,17 +587,17 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): @property def function_name(self): """ The name of the function that implements this kernel """ - # Use permuted_matrix_sequence here since this is more consistent with + # Use matrix_sequence_quadrature_permuted here since this is more consistent with # the vectorized case - name = "sfimpl_{}{}".format("_".join(str(m) for m in self.permuted_matrix_sequence), + name = "sfimpl_{}{}".format("_".join(str(m) for m in self.matrix_sequence_quadrature_permuted), self.interface.function_name_suffix) # On unstructured we need different permutation of the input to realize # different permuation of quadrature points on self and neighbor. Mangle # the permutation of the quadrature points into the name to generate # sperate functions. - if self.quadrature_permutation != tuple(range(len(self.matrix_sequence))): - name_quad_perm = "_qpperm_{}".format("".join(str(a) for a in self.quadrature_permutation)) + if self.interface.quadrature_permutation != tuple(range(len(self.matrix_sequence))): + name_quad_perm = "_qpperm_{}".format("".join(str(a) for a in self.interface.quadrature_permutation)) name = name + name_quad_perm return name @@ -375,7 +605,10 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): @property def parallel_key(self): """ A key that identifies parallellizable kernels. """ - return tuple(m.basis_size for m in self.permuted_matrix_sequence) + (self.stage, self.buffer, self.interface.within_inames) + # TODO: For now we do not vectorize SumfactKernels with different + # quadrature_permutation. This should be handled like upper/lower + # vectorization + return tuple(m.quadrature_size for m in self.matrix_sequence_quadrature_permuted) + tuple(m.basis_size for m in self.matrix_sequence_quadrature_permuted) + (self.stage, self.buffer, self.interface.within_inames) + (self.interface.direct_is_possible, self.interface.quadrature_permutation) @property def cache_key(self): @@ -440,7 +673,7 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): return 0 @property - def permuted_matrix_sequence(self): + def matrix_sequence_quadrature_permuted(self): """Matrix sequence ordered according to desired quadrature point ordered Except for face integrals on 3D unstructured grids this will just be @@ -448,9 +681,27 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): to ensure that quadrature points are visited in the same order on self and neighbor. """ - perm = self.quadrature_permutation - permuted_matrix_sequence = permute_forward(self.matrix_sequence, perm) - return permuted_matrix_sequence + perm = self.interface.quadrature_permutation + matrix_sequence_quadrature_permuted = permute_forward(self.matrix_sequence, perm) + return matrix_sequence_quadrature_permuted + + @property + def matrix_sequence_cost_permuted(self): + """Permute matrix_sequence_qudrature_permuted to minimize flop cost + + A clever ordering can lead to a reduced complexity. This will + e.g. happen at faces where we only have one quadratue point m_l=1 if l + is the normal direction of the face. + + Rule of thumb: small m's early and large n's late. + """ + perm = sumfact_cost_permutation_strategy(self.matrix_sequence_quadrature_permuted, self.stage) + matrix_sequence_cost_permuted = permute_forward(self.matrix_sequence_quadrature_permuted, perm) + return matrix_sequence_cost_permuted + + @property + def cost_permutation(self): + return sumfact_cost_permutation_strategy(self.matrix_sequence_quadrature_permuted, self.stage) @property def quadrature_shape(self): @@ -458,18 +709,27 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): Takes into account the lower dimensionality of faces and vectorization. """ - return tuple(mat.quadrature_size for mat in self.permuted_matrix_sequence) + return tuple(mat.quadrature_size for mat in self.matrix_sequence_quadrature_permuted) def quadrature_index(self, sf, visitor): - quad_inames = visitor.quadrature_inames() - if len(self.permuted_matrix_sequence) == local_dimension(): + if visitor.current_info[1] is None: + element = None + element_index = 0 + else: + element = visitor.current_info[1].element + element_index = visitor.current_info[1].element_index + if isinstance(element, MixedElement): + element = element.extract_component(element_index)[1] + + quad_inames = quadrature_inames(element) + if len(self.matrix_sequence_quadrature_permuted) == local_dimension(): return tuple(prim.Variable(i) for i in quad_inames) # Traverse all the quadrature inames and map them to their correct direction index = [] i = 0 for d in range(world_dimension()): - if self.permuted_matrix_sequence[d].face is None: + if self.matrix_sequence_quadrature_permuted[d].face is None: index.append(prim.Variable(quad_inames[i])) i = i + 1 else: @@ -492,7 +752,7 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): Takes into account vectorization. """ - return tuple(mat.basis_size for mat in self.permuted_matrix_sequence) + return tuple(mat.basis_size for mat in self.matrix_sequence_quadrature_permuted) @property def dof_dimtags(self): @@ -566,8 +826,7 @@ class SumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable): def operations(self): """ The total number of floating point operations for the kernel to be carried out """ - from dune.codegen.sumfact.permutation import flop_cost - return flop_cost(self.permuted_matrix_sequence) + return flop_cost(self.matrix_sequence_cost_permuted) # Extract the argument list and store it on the class. This needs to be done @@ -594,19 +853,22 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) assert len(set(k.within_inames for k in kernels)) == 1 assert len(set(k.predicates for k in kernels)) == 1 + # For now we don't mix direct and non_direct input. Could be done in an upper/lower way. + assert len(set(tuple(k.interface.direct_is_possible for k in kernels))) == 1 + # Assert properties of the matrix sequence of the underlying kernels for i in range(kernels[0].length): - assert len(set(tuple(k.permuted_matrix_sequence[i].rows for k in kernels))) == 1 - assert len(set(tuple(k.permuted_matrix_sequence[i].cols for k in kernels))) == 1 - assert len(set(tuple(k.permuted_matrix_sequence[i].direction for k in kernels))) == 1 - assert len(set(tuple(k.permuted_matrix_sequence[i].transpose for k in kernels))) == 1 + assert len(set(tuple(k.matrix_sequence_quadrature_permuted[i].rows for k in kernels))) == 1 + assert len(set(tuple(k.matrix_sequence_quadrature_permuted[i].cols for k in kernels))) == 1 + assert len(set(tuple(k.matrix_sequence_quadrature_permuted[i].direction for k in kernels))) == 1 + assert len(set(tuple(k.matrix_sequence_quadrature_permuted[i].transpose for k in kernels))) == 1 # Join the instruction dependencies of all subkernels insn_dep = insn_dep.union(k.insn_dep for k in kernels) - # Assert that quadrature permutation is the same for all kernels + # Assert that the cost_permutation is the same for all kernels for k in kernels: - assert k.quadrature_permutation == kernels[0].quadrature_permutation + assert k.interface.cost_permutation == kernels[0].interface.cost_permutation # We currently assume that all subkernels are consecutive, 0-based within the vector assert None not in kernels @@ -631,7 +893,7 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) # Above stringifier just calls back into this return "VSF{}:[{}]->[{}]".format(self.stage, ", ".join(str(k.interface) for k in self.kernels), - ", ".join(str(mat) for mat in self.matrix_sequence)) + ", ".join(str(mat) for mat in self.matrix_sequence_quadrature_permuted)) mapper_method = "map_vectorized_sumfact_kernel" @@ -643,7 +905,7 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) # @property def function_name(self): - return "sfimpl_{}{}".format("_".join(str(m) for m in self.matrix_sequence), + return "sfimpl_{}{}".format("_".join(str(m) for m in self.matrix_sequence_quadrature_permuted), self.interface.function_name_suffix) @property @@ -652,21 +914,42 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) Any two sum factorization kernels having the same cache_key are realized simulatenously! """ - return (self.matrix_sequence, self.restriction, self.stage, self.buffer) + return (self.matrix_sequence_quadrature_permuted, self.restriction, self.stage, self.buffer) # # Deduce all data fields of normal sum factorization kernels from the underlying kernels # @property def matrix_sequence(self): - return tuple(BasisTabulationMatrixArray(tuple(k.permuted_matrix_sequence[i] for k in self.kernels), + # VectorizedSumfactKernel has no knowledge about the matrix_sequence + # ordered according to directions 0,1,... since it is constructed based + # on permuted matrix sequences. + raise RuntimeError("matrix_sequence should not be used on VectorizedSumfactKernel.") + + @property + def matrix_sequence_quadrature_permuted(self): + # Construct quadrature permuted matrix sequence from scalar case + return tuple(BasisTabulationMatrixArray(tuple(k.matrix_sequence_quadrature_permuted[i] for k in self.kernels), width=self.vector_width, ) for i in range(self.length)) @property - def permuted_matrix_sequence(self): - return self.matrix_sequence + def matrix_sequence_cost_permuted(self): + # Construct cost permuted matrix sequence from scalar case + matrix_sequence = tuple(BasisTabulationMatrixArray(tuple(k.matrix_sequence_cost_permuted[i] for k in self.kernels), + width=self.vector_width,) + for i in range(self.length)) + + # This should already be cost optimal + perm = sumfact_cost_permutation_strategy(matrix_sequence, self.stage) + assert perm == tuple(i for i in range(len(perm))) + + return matrix_sequence + + @property + def cost_permutation(self): + raise RuntimeError("cost_permutation should not be used on VectorizedSumfactKernel.") @property def stage(self): @@ -678,7 +961,10 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) @property def quadrature_permutation(self): - return self.kernels[0].quadrature_permutation + # The quadrature_permutations of the underlying scalar kernels can be + # different from kernel to kernel. So there is no well defined + # quadrature_permutation on the VectorizedSumfactKernel. + raise RuntimeError("quadrature_permutation should not be used on VectorizedSumfactKernel.") @property def within_inames(self): @@ -736,8 +1022,17 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) def horizontal_index(self, sf): for i, k in enumerate(self.kernels): - if sf.inout_key == k.inout_key: - if tuple(mat.derivative for mat in sf.permuted_matrix_sequence) == tuple(mat.derivative for mat in k.permuted_matrix_sequence): + # We need to identify to which part of the vectorized kernel sf + # corresponds. Since splitting might change the cost_permutation we + # exclude it in the comparison below. We also make sure to check + # that derivatives are the same. + from copy import deepcopy + sf_interface = deepcopy(sf.interface) + sf_interface._cost_permutation = None + k_interface = deepcopy(k.interface) + k_interface._cost_permutation = None + if repr(sf_interface) == repr(k_interface): + if tuple(mat.derivative for mat in sf.matrix_sequence_quadrature_permuted) == tuple(mat.derivative for mat in k.matrix_sequence_quadrature_permuted): return i return 0 @@ -746,11 +1041,11 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) quad_inames = visitor.quadrature_inames() index = [] - if len(self.matrix_sequence) == local_dimension(): + if len(self.matrix_sequence_quadrature_permuted) == local_dimension(): for d in range(local_dimension()): addindex = prim.Variable(quad_inames[d]) - if self.matrix_sequence[d].slice_size: + if self.matrix_sequence_quadrature_permuted[d].slice_size: addindex = addindex // self.vertical_width index.append(addindex) @@ -758,10 +1053,10 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) # Traverse all the quadrature inames and map them to their correct direction i = 0 for d in range(world_dimension()): - if self.matrix_sequence[d].face is None: + if self.matrix_sequence_quadrature_permuted[d].face is None: addindex = prim.Variable(quad_inames[i]) - if self.matrix_sequence[d].slice_size: + if self.matrix_sequence_quadrature_permuted[d].slice_size: addindex = addindex // self.vertical_width index.append(addindex) @@ -775,15 +1070,15 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) quad_inames = visitor.quadrature_inames() sliced = 0 - if len(sf.permuted_matrix_sequence) == local_dimension(): + if len(self.matrix_sequence_quadrature_permuted) == local_dimension(): for d in range(local_dimension()): - if self.matrix_sequence[d].slice_size: + if self.matrix_sequence_quadrature_permuted[d].slice_size: sliced = prim.Variable(quad_inames[d]) else: i = 0 for d in range(world_dimension()): - if self.matrix_sequence[d].face is None: - if self.matrix_sequence[d].slice_size: + if self.matrix_sequence_quadrature_permuted[d].face is None: + if self.matrix_sequence_quadrature_permuted[d].slice_size: sliced = prim.Variable(quad_inames[i]) i = i + 1 @@ -791,7 +1086,7 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) @property def quadrature_shape(self): - return tuple(mat.quadrature_size for mat in self.matrix_sequence) + (self.vector_width,) + return tuple(mat.quadrature_size for mat in self.matrix_sequence_quadrature_permuted) + (self.vector_width,) def quadrature_index(self, sf, visitor, direct_index=None): quad = self._quadrature_index(sf, visitor) @@ -809,7 +1104,7 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) @property def dof_shape(self): - return tuple(mat.basis_size for mat in self.matrix_sequence) + (self.vector_width,) + return tuple(mat.basis_size for mat in self.matrix_sequence_quadrature_permuted) + (self.vector_width,) @property def dof_dimtags(self): @@ -844,8 +1139,8 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) """ The total number of bytes needed from RAM for the kernel to be executed - neglecting the existence of caches of course """ - dofs = product(mat.basis_size for mat in self.matrix_sequence) - matrices = sum(mat.memory_traffic for mat in set(self.matrix_sequence)) + dofs = product(mat.basis_size for mat in self.matrix_sequence_quadrature_permuted) + matrices = sum(mat.memory_traffic for mat in set(self.matrix_sequence_quadrature_permuted)) fbytes = get_option("precision_bits") / 8 return (dofs + matrices) * fbytes @@ -854,5 +1149,4 @@ class VectorizedSumfactKernel(SumfactKernelBase, ImmutableRecord, prim.Variable) def operations(self): """ The total number of floating point operations for the kernel to be carried out """ - from dune.codegen.sumfact.permutation import flop_cost - return flop_cost(self.matrix_sequence) + return flop_cost(self.matrix_sequence_cost_permuted) diff --git a/python/dune/codegen/sumfact/vectorization.py b/python/dune/codegen/sumfact/vectorization.py index fc555f2c3afafce212a6d266b6817f57e2d9683f..e753652b10b3ac9b1765ee071bce1ccebd15f6b1 100644 --- a/python/dune/codegen/sumfact/vectorization.py +++ b/python/dune/codegen/sumfact/vectorization.py @@ -170,6 +170,8 @@ def quadrature_penalized_strategy_cost(strat_tuple): # Evaluate the original cost function. This result will be scaled by this function. cost = strategy_cost(strat_tuple) + if cost is 0: + return 0 # Get the total number of Flops done in sum factorization kernels sf_flops = accumulate_for_strategy(strategy, lambda sf: sf.operations) @@ -316,7 +318,7 @@ def level1_optimal_vectorization_strategy(sumfacts, width): sf = next(iter(sumfacts)) depth = 1 while depth <= width: - i = 0 if sf.permuted_matrix_sequence[0].face is None else 1 + i = 0 if sf.matrix_sequence_quadrature_permuted[0].face is None else 1 quad = list(quadrature_points_per_direction()) quad[i] = round_to_multiple(quad[i], depth) quad_points.append(tuple(quad)) @@ -452,17 +454,22 @@ def get_vectorization_dict(sumfacts, vertical, horizontal, qp): continue # Determine the slicing direction - slice_direction = 0 if sf.permuted_matrix_sequence[0].face is None else 1 + slice_direction = 0 if sf.matrix_sequence_quadrature_permuted[0].face is None else 1 if qp[slice_direction] % vertical != 0: return None # Split the basis tabulation matrices - oldtab = sf.permuted_matrix_sequence[slice_direction] + oldtab = sf.matrix_sequence_quadrature_permuted[slice_direction] for i in range(vertical): - seq = list(sf.permuted_matrix_sequence) + seq = list(sf.matrix_sequence_quadrature_permuted) seq[slice_direction] = oldtab.copy(slice_size=vertical, slice_index=i) - kernels.append(sf.copy(matrix_sequence=tuple(seq))) + + # Create new sf kernel with new interface + kwargs = sf.interface.get_keyword_arguments() + kwargs.update({'matrix_sequence': tuple(seq)}) + newinterface = type(sf.interface)(**kwargs) + kernels.append(sf.copy(matrix_sequence=tuple(seq), interface=newinterface)) # Join the new kernels into a sum factorization node buffer = get_counted_variable("joined_buffer") diff --git a/test/sumfact/poisson/CMakeLists.txt b/test/sumfact/poisson/CMakeLists.txt index 91e9e60755a314f083cbb3d25088a52192c9cade..307e6d43e25caa89234a884156c7ee5643f16b8f 100644 --- a/test/sumfact/poisson/CMakeLists.txt +++ b/test/sumfact/poisson/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(facedir-facemod-variation) + #==================== # Poisson CG in 2D/3D #==================== @@ -71,14 +73,19 @@ if(consistent-edge-orientation_FOUND) INIFILE poisson_dg_3d_gmsh.mini ANALYZE_GRID ) + dune_add_formcompiler_system_test(UFLFILE poisson_dg_2d.ufl + BASENAME sumfact_poisson_fastdg_2d_gmsh + INIFILE poisson_fastdg_2d_gmsh.mini + ANALYZE_GRID + ) dune_add_formcompiler_system_test(UFLFILE poisson_dg_3d.ufl BASENAME sumfact_poisson_fastdg_3d_gmsh INIFILE poisson_fastdg_3d_gmsh.mini ANALYZE_GRID ) - dune_symlink_to_source_files(FILES square_quad.msh square_quad_consistent.msh) - dune_symlink_to_source_files(FILES cube_hexa_2.msh cube_hexa_2_consistent.msh) - dune_symlink_to_source_files(FILES cube_hexa.msh cube_hexa_consistent.msh) + dune_symlink_to_source_files(FILES square_quad.msh) + dune_symlink_to_source_files(FILES cube_hexa_2.msh) + dune_symlink_to_source_files(FILES cube_hexa.msh) endif() #============================================= diff --git a/test/sumfact/poisson/cube_hexa_2_consistent.msh b/test/sumfact/poisson/cube_hexa_2_consistent.msh deleted file mode 100644 index 9516c8ae4871eb72b8a60b9d5db680ba8decf5b8..0000000000000000000000000000000000000000 --- a/test/sumfact/poisson/cube_hexa_2_consistent.msh +++ /dev/null @@ -1,44 +0,0 @@ -$MeshFormat -2.0 0 8 -$EndMeshFormat -$Nodes -27 -1 0.5 0 0 -2 0.5 0.5 0 -3 0 0.5 0 -4 0 0 0 -5 0.5 0 0.5 -7 0 0.5 0.5 -8 0 0 0.5 -9 0.5 0 1 -10 0.5 0.5 1 -11 0 0.5 1 -12 0 0 1 -13 0.5 1 0 -14 0 1 0 -15 0.5 1 0.5 -16 0 1 0.5 -17 0.5 1 1 -18 0 1 1 -19 1 0 0 -20 1 0.5 0 -21 1 0 0.5 -22 1 0.5 0.5 -23 1 0 1 -24 1 0.5 1 -25 1 1 0 -26 1 1 0.5 -27 1 1 1 -6 0.5 0.5 0.5 -$EndNodes -$Elements -8 -1 5 0 2 3 4 1 6 7 8 5 -2 5 0 6 7 8 5 10 11 12 9 -3 5 0 2 13 14 3 6 15 16 7 -4 5 0 6 15 16 7 10 17 18 11 -5 5 0 2 1 19 20 6 5 21 22 -6 5 0 6 5 21 22 10 9 23 24 -7 5 0 2 20 25 13 6 22 26 15 -8 5 0 6 22 26 15 10 24 27 17 -$EndElements diff --git a/test/sumfact/poisson/cube_hexa_consistent.msh b/test/sumfact/poisson/cube_hexa_consistent.msh deleted file mode 100644 index b14f54f4a303156b44dc1e929c58c35c9a887637..0000000000000000000000000000000000000000 --- a/test/sumfact/poisson/cube_hexa_consistent.msh +++ /dev/null @@ -1,1250 +0,0 @@ -$MeshFormat -2.0 0 8 -$EndMeshFormat -$Nodes -729 -1 0 0 0 -2 0.125 0 0 -3 0.125 0.125 0 -4 0 0.125 0 -5 0.125 0.25 0 -6 0 0.25 0 -7 0.125 0.375 0 -8 0 0.375 0 -9 0.125 0.5 0 -10 0 0.5 0 -11 0.125 0.625 0 -12 0 0.625 0 -13 0.125 0.75 0 -14 0 0.75 0 -15 0.125 0.875 0 -16 0 0.875 0 -17 0.125 1 0 -18 0 1 0 -19 0.25 0 0 -20 0.25 0.125 0 -21 0.25 0.25 0 -22 0.25 0.375 0 -23 0.25 0.5 0 -24 0.25 0.625 0 -25 0.25 0.75 0 -26 0.25 0.875 0 -27 0.25 1 0 -28 0.375 0 0 -29 0.375 0.125 0 -30 0.375 0.25 0 -31 0.375 0.375 0 -32 0.375 0.5 0 -33 0.375 0.625 0 -34 0.375 0.75 0 -35 0.375 0.875 0 -36 0.375 1 0 -37 0.5 0 0 -38 0.5 0.125 0 -39 0.5 0.25 0 -40 0.5 0.375 0 -41 0.5 0.5 0 -42 0.5 0.625 0 -43 0.5 0.75 0 -44 0.5 0.875 0 -45 0.5 1 0 -46 0.625 0 0 -47 0.625 0.125 0 -48 0.625 0.25 0 -49 0.625 0.375 0 -50 0.625 0.5 0 -51 0.625 0.625 0 -52 0.625 0.75 0 -53 0.625 0.875 0 -54 0.625 1 0 -55 0.75 0 0 -56 0.75 0.125 0 -57 0.75 0.25 0 -58 0.75 0.375 0 -59 0.75 0.5 0 -60 0.75 0.625 0 -61 0.75 0.75 0 -62 0.75 0.875 0 -63 0.75 1 0 -64 0.875 0 0 -65 0.875 0.125 0 -66 0.875 0.25 0 -67 0.875 0.375 0 -68 0.875 0.5 0 -69 0.875 0.625 0 -70 0.875 0.75 0 -71 0.875 0.875 0 -72 0.875 1 0 -73 1 0 0 -74 1 0.125 0 -75 1 0.25 0 -76 1 0.375 0 -77 1 0.5 0 -78 1 0.625 0 -79 1 0.75 0 -80 1 0.875 0 -81 1 1 0 -82 0.125 0 0.125 -83 0 0 0.125 -84 0.125 0 0.25 -85 0 0 0.25 -86 0.125 0 0.375 -87 0 0 0.375 -88 0.125 0 0.5 -89 0 0 0.5 -90 0.125 0 0.625 -91 0 0 0.625 -92 0.125 0 0.75 -93 0 0 0.75 -94 0.125 0 0.875 -95 0 0 0.875 -96 0.125 0 1 -97 0 0 1 -98 0.25 0 0.125 -99 0.25 0 0.25 -100 0.25 0 0.375 -101 0.25 0 0.5 -102 0.25 0 0.625 -103 0.25 0 0.75 -104 0.25 0 0.875 -105 0.25 0 1 -106 0.375 0 0.125 -107 0.375 0 0.25 -108 0.375 0 0.375 -109 0.375 0 0.5 -110 0.375 0 0.625 -111 0.375 0 0.75 -112 0.375 0 0.875 -113 0.375 0 1 -114 0.5 0 0.125 -115 0.5 0 0.25 -116 0.5 0 0.375 -117 0.5 0 0.5 -118 0.5 0 0.625 -119 0.5 0 0.75 -120 0.5 0 0.875 -121 0.5 0 1 -122 0.625 0 0.125 -123 0.625 0 0.25 -124 0.625 0 0.375 -125 0.625 0 0.5 -126 0.625 0 0.625 -127 0.625 0 0.75 -128 0.625 0 0.875 -129 0.625 0 1 -130 0.75 0 0.125 -131 0.75 0 0.25 -132 0.75 0 0.375 -133 0.75 0 0.5 -134 0.75 0 0.625 -135 0.75 0 0.75 -136 0.75 0 0.875 -137 0.75 0 1 -138 0.875 0 0.125 -139 0.875 0 0.25 -140 0.875 0 0.375 -141 0.875 0 0.5 -142 0.875 0 0.625 -143 0.875 0 0.75 -144 0.875 0 0.875 -145 0.875 0 1 -146 1 0 0.125 -147 1 0 0.25 -148 1 0 0.375 -149 1 0 0.5 -150 1 0 0.625 -151 1 0 0.75 -152 1 0 0.875 -153 1 0 1 -154 1 0.125 0.125 -155 1 0.125 0.25 -156 1 0.125 0.375 -157 1 0.125 0.5 -158 1 0.125 0.625 -159 1 0.125 0.75 -160 1 0.125 0.875 -161 1 0.125 1 -162 1 0.25 0.125 -163 1 0.25 0.25 -164 1 0.25 0.375 -165 1 0.25 0.5 -166 1 0.25 0.625 -167 1 0.25 0.75 -168 1 0.25 0.875 -169 1 0.25 1 -170 1 0.375 0.125 -171 1 0.375 0.25 -172 1 0.375 0.375 -173 1 0.375 0.5 -174 1 0.375 0.625 -175 1 0.375 0.75 -176 1 0.375 0.875 -177 1 0.375 1 -178 1 0.5 0.125 -179 1 0.5 0.25 -180 1 0.5 0.375 -181 1 0.5 0.5 -182 1 0.5 0.625 -183 1 0.5 0.75 -184 1 0.5 0.875 -185 1 0.5 1 -186 1 0.625 0.125 -187 1 0.625 0.25 -188 1 0.625 0.375 -189 1 0.625 0.5 -190 1 0.625 0.625 -191 1 0.625 0.75 -192 1 0.625 0.875 -193 1 0.625 1 -194 1 0.75 0.125 -195 1 0.75 0.25 -196 1 0.75 0.375 -197 1 0.75 0.5 -198 1 0.75 0.625 -199 1 0.75 0.75 -200 1 0.75 0.875 -201 1 0.75 1 -202 1 0.875 0.125 -203 1 0.875 0.25 -204 1 0.875 0.375 -205 1 0.875 0.5 -206 1 0.875 0.625 -207 1 0.875 0.75 -208 1 0.875 0.875 -209 1 0.875 1 -210 1 1 0.125 -211 1 1 0.25 -212 1 1 0.375 -213 1 1 0.5 -214 1 1 0.625 -215 1 1 0.75 -216 1 1 0.875 -217 1 1 1 -218 0.875 1 0.125 -219 0.875 1 0.25 -220 0.875 1 0.375 -221 0.875 1 0.5 -222 0.875 1 0.625 -223 0.875 1 0.75 -224 0.875 1 0.875 -225 0.875 1 1 -226 0.75 1 0.125 -227 0.75 1 0.25 -228 0.75 1 0.375 -229 0.75 1 0.5 -230 0.75 1 0.625 -231 0.75 1 0.75 -232 0.75 1 0.875 -233 0.75 1 1 -234 0.625 1 0.125 -235 0.625 1 0.25 -236 0.625 1 0.375 -237 0.625 1 0.5 -238 0.625 1 0.625 -239 0.625 1 0.75 -240 0.625 1 0.875 -241 0.625 1 1 -242 0.5 1 0.125 -243 0.5 1 0.25 -244 0.5 1 0.375 -245 0.5 1 0.5 -246 0.5 1 0.625 -247 0.5 1 0.75 -248 0.5 1 0.875 -249 0.5 1 1 -250 0.375 1 0.125 -251 0.375 1 0.25 -252 0.375 1 0.375 -253 0.375 1 0.5 -254 0.375 1 0.625 -255 0.375 1 0.75 -256 0.375 1 0.875 -257 0.375 1 1 -258 0.25 1 0.125 -259 0.25 1 0.25 -260 0.25 1 0.375 -261 0.25 1 0.5 -262 0.25 1 0.625 -263 0.25 1 0.75 -264 0.25 1 0.875 -265 0.25 1 1 -266 0.125 1 0.125 -267 0.125 1 0.25 -268 0.125 1 0.375 -269 0.125 1 0.5 -270 0.125 1 0.625 -271 0.125 1 0.75 -272 0.125 1 0.875 -273 0.125 1 1 -274 0 1 0.125 -275 0 1 0.25 -276 0 1 0.375 -277 0 1 0.5 -278 0 1 0.625 -279 0 1 0.75 -280 0 1 0.875 -281 0 1 1 -282 0 0.875 0.125 -283 0 0.875 0.25 -284 0 0.875 0.375 -285 0 0.875 0.5 -286 0 0.875 0.625 -287 0 0.875 0.75 -288 0 0.875 0.875 -289 0 0.875 1 -290 0 0.75 0.125 -291 0 0.75 0.25 -292 0 0.75 0.375 -293 0 0.75 0.5 -294 0 0.75 0.625 -295 0 0.75 0.75 -296 0 0.75 0.875 -297 0 0.75 1 -298 0 0.625 0.125 -299 0 0.625 0.25 -300 0 0.625 0.375 -301 0 0.625 0.5 -302 0 0.625 0.625 -303 0 0.625 0.75 -304 0 0.625 0.875 -305 0 0.625 1 -306 0 0.5 0.125 -307 0 0.5 0.25 -308 0 0.5 0.375 -309 0 0.5 0.5 -310 0 0.5 0.625 -311 0 0.5 0.75 -312 0 0.5 0.875 -313 0 0.5 1 -314 0 0.375 0.125 -315 0 0.375 0.25 -316 0 0.375 0.375 -317 0 0.375 0.5 -318 0 0.375 0.625 -319 0 0.375 0.75 -320 0 0.375 0.875 -321 0 0.375 1 -322 0 0.25 0.125 -323 0 0.25 0.25 -324 0 0.25 0.375 -325 0 0.25 0.5 -326 0 0.25 0.625 -327 0 0.25 0.75 -328 0 0.25 0.875 -329 0 0.25 1 -330 0 0.125 0.125 -331 0 0.125 0.25 -332 0 0.125 0.375 -333 0 0.125 0.5 -334 0 0.125 0.625 -335 0 0.125 0.75 -336 0 0.125 0.875 -337 0 0.125 1 -338 0.125 0.125 1 -339 0.125 0.25 1 -340 0.125 0.375 1 -341 0.125 0.5 1 -342 0.125 0.625 1 -343 0.125 0.75 1 -344 0.125 0.875 1 -345 0.25 0.125 1 -346 0.25 0.25 1 -347 0.25 0.375 1 -348 0.25 0.5 1 -349 0.25 0.625 1 -350 0.25 0.75 1 -351 0.25 0.875 1 -352 0.375 0.125 1 -353 0.375 0.25 1 -354 0.375 0.375 1 -355 0.375 0.5 1 -356 0.375 0.625 1 -357 0.375 0.75 1 -358 0.375 0.875 1 -359 0.5 0.125 1 -360 0.5 0.25 1 -361 0.5 0.375 1 -362 0.5 0.5 1 -363 0.5 0.625 1 -364 0.5 0.75 1 -365 0.5 0.875 1 -366 0.625 0.125 1 -367 0.625 0.25 1 -368 0.625 0.375 1 -369 0.625 0.5 1 -370 0.625 0.625 1 -371 0.625 0.75 1 -372 0.625 0.875 1 -373 0.75 0.125 1 -374 0.75 0.25 1 -375 0.75 0.375 1 -376 0.75 0.5 1 -377 0.75 0.625 1 -378 0.75 0.75 1 -379 0.75 0.875 1 -380 0.875 0.125 1 -381 0.875 0.25 1 -382 0.875 0.375 1 -383 0.875 0.5 1 -384 0.875 0.625 1 -385 0.875 0.75 1 -386 0.875 0.875 1 -387 0.125 0.125 0.125 -388 0.125 0.125 0.25 -389 0.125 0.125 0.375 -390 0.125 0.125 0.5 -391 0.125 0.125 0.625 -392 0.125 0.125 0.75 -393 0.125 0.125 0.875 -394 0.125 0.25 0.125 -395 0.125 0.25 0.25 -396 0.125 0.25 0.375 -397 0.125 0.25 0.5 -398 0.125 0.25 0.625 -399 0.125 0.25 0.75 -400 0.125 0.25 0.875 -401 0.125 0.375 0.125 -402 0.125 0.375 0.25 -403 0.125 0.375 0.375 -404 0.125 0.375 0.5 -405 0.125 0.375 0.625 -406 0.125 0.375 0.75 -407 0.125 0.375 0.875 -408 0.125 0.5 0.125 -409 0.125 0.5 0.25 -410 0.125 0.5 0.375 -411 0.125 0.5 0.5 -412 0.125 0.5 0.625 -413 0.125 0.5 0.75 -414 0.125 0.5 0.875 -415 0.125 0.625 0.125 -416 0.125 0.625 0.25 -417 0.125 0.625 0.375 -418 0.125 0.625 0.5 -419 0.125 0.625 0.625 -420 0.125 0.625 0.75 -421 0.125 0.625 0.875 -422 0.125 0.75 0.125 -423 0.125 0.75 0.25 -424 0.125 0.75 0.375 -425 0.125 0.75 0.5 -426 0.125 0.75 0.625 -427 0.125 0.75 0.75 -428 0.125 0.75 0.875 -429 0.125 0.875 0.125 -430 0.125 0.875 0.25 -431 0.125 0.875 0.375 -432 0.125 0.875 0.5 -433 0.125 0.875 0.625 -434 0.125 0.875 0.75 -435 0.125 0.875 0.875 -436 0.25 0.125 0.125 -437 0.25 0.125 0.25 -438 0.25 0.125 0.375 -439 0.25 0.125 0.5 -440 0.25 0.125 0.625 -441 0.25 0.125 0.75 -442 0.25 0.125 0.875 -443 0.25 0.25 0.125 -444 0.25 0.25 0.25 -445 0.25 0.25 0.375 -446 0.25 0.25 0.5 -447 0.25 0.25 0.625 -448 0.25 0.25 0.75 -449 0.25 0.25 0.875 -450 0.25 0.375 0.125 -451 0.25 0.375 0.25 -452 0.25 0.375 0.375 -453 0.25 0.375 0.5 -454 0.25 0.375 0.625 -455 0.25 0.375 0.75 -456 0.25 0.375 0.875 -457 0.25 0.5 0.125 -458 0.25 0.5 0.25 -459 0.25 0.5 0.375 -460 0.25 0.5 0.5 -461 0.25 0.5 0.625 -462 0.25 0.5 0.75 -463 0.25 0.5 0.875 -464 0.25 0.625 0.125 -465 0.25 0.625 0.25 -466 0.25 0.625 0.375 -467 0.25 0.625 0.5 -468 0.25 0.625 0.625 -469 0.25 0.625 0.75 -470 0.25 0.625 0.875 -471 0.25 0.75 0.125 -472 0.25 0.75 0.25 -473 0.25 0.75 0.375 -474 0.25 0.75 0.5 -475 0.25 0.75 0.625 -476 0.25 0.75 0.75 -477 0.25 0.75 0.875 -478 0.25 0.875 0.125 -479 0.25 0.875 0.25 -480 0.25 0.875 0.375 -481 0.25 0.875 0.5 -482 0.25 0.875 0.625 -483 0.25 0.875 0.75 -484 0.25 0.875 0.875 -485 0.375 0.125 0.125 -486 0.375 0.125 0.25 -487 0.375 0.125 0.375 -488 0.375 0.125 0.5 -489 0.375 0.125 0.625 -490 0.375 0.125 0.75 -491 0.375 0.125 0.875 -492 0.375 0.25 0.125 -493 0.375 0.25 0.25 -494 0.375 0.25 0.375 -495 0.375 0.25 0.5 -496 0.375 0.25 0.625 -497 0.375 0.25 0.75 -498 0.375 0.25 0.875 -499 0.375 0.375 0.125 -500 0.375 0.375 0.25 -501 0.375 0.375 0.375 -502 0.375 0.375 0.5 -503 0.375 0.375 0.625 -504 0.375 0.375 0.75 -505 0.375 0.375 0.875 -506 0.375 0.5 0.125 -507 0.375 0.5 0.25 -508 0.375 0.5 0.375 -509 0.375 0.5 0.5 -510 0.375 0.5 0.625 -511 0.375 0.5 0.75 -512 0.375 0.5 0.875 -513 0.375 0.625 0.125 -514 0.375 0.625 0.25 -515 0.375 0.625 0.375 -516 0.375 0.625 0.5 -517 0.375 0.625 0.625 -518 0.375 0.625 0.75 -519 0.375 0.625 0.875 -520 0.375 0.75 0.125 -521 0.375 0.75 0.25 -522 0.375 0.75 0.375 -523 0.375 0.75 0.5 -524 0.375 0.75 0.625 -525 0.375 0.75 0.75 -526 0.375 0.75 0.875 -527 0.375 0.875 0.125 -528 0.375 0.875 0.25 -529 0.375 0.875 0.375 -530 0.375 0.875 0.5 -531 0.375 0.875 0.625 -532 0.375 0.875 0.75 -533 0.375 0.875 0.875 -534 0.5 0.125 0.125 -535 0.5 0.125 0.25 -536 0.5 0.125 0.375 -537 0.5 0.125 0.5 -538 0.5 0.125 0.625 -539 0.5 0.125 0.75 -540 0.5 0.125 0.875 -541 0.5 0.25 0.125 -542 0.5 0.25 0.25 -543 0.5 0.25 0.375 -544 0.5 0.25 0.5 -545 0.5 0.25 0.625 -546 0.5 0.25 0.75 -547 0.5 0.25 0.875 -548 0.5 0.375 0.125 -549 0.5 0.375 0.25 -550 0.5 0.375 0.375 -551 0.5 0.375 0.5 -552 0.5 0.375 0.625 -553 0.5 0.375 0.75 -554 0.5 0.375 0.875 -555 0.5 0.5 0.125 -556 0.5 0.5 0.25 -557 0.5 0.5 0.375 -558 0.5 0.5 0.5 -559 0.5 0.5 0.625 -560 0.5 0.5 0.75 -561 0.5 0.5 0.875 -562 0.5 0.625 0.125 -563 0.5 0.625 0.25 -564 0.5 0.625 0.375 -565 0.5 0.625 0.5 -566 0.5 0.625 0.625 -567 0.5 0.625 0.75 -568 0.5 0.625 0.875 -569 0.5 0.75 0.125 -570 0.5 0.75 0.25 -571 0.5 0.75 0.375 -572 0.5 0.75 0.5 -573 0.5 0.75 0.625 -574 0.5 0.75 0.75 -575 0.5 0.75 0.875 -576 0.5 0.875 0.125 -577 0.5 0.875 0.25 -578 0.5 0.875 0.375 -579 0.5 0.875 0.5 -580 0.5 0.875 0.625 -581 0.5 0.875 0.75 -582 0.5 0.875 0.875 -583 0.625 0.125 0.125 -584 0.625 0.125 0.25 -585 0.625 0.125 0.375 -586 0.625 0.125 0.5 -587 0.625 0.125 0.625 -588 0.625 0.125 0.75 -589 0.625 0.125 0.875 -590 0.625 0.25 0.125 -591 0.625 0.25 0.25 -592 0.625 0.25 0.375 -593 0.625 0.25 0.5 -594 0.625 0.25 0.625 -595 0.625 0.25 0.75 -596 0.625 0.25 0.875 -597 0.625 0.375 0.125 -598 0.625 0.375 0.25 -599 0.625 0.375 0.375 -600 0.625 0.375 0.5 -601 0.625 0.375 0.625 -602 0.625 0.375 0.75 -603 0.625 0.375 0.875 -604 0.625 0.5 0.125 -605 0.625 0.5 0.25 -606 0.625 0.5 0.375 -607 0.625 0.5 0.5 -608 0.625 0.5 0.625 -609 0.625 0.5 0.75 -610 0.625 0.5 0.875 -611 0.625 0.625 0.125 -612 0.625 0.625 0.25 -613 0.625 0.625 0.375 -614 0.625 0.625 0.5 -615 0.625 0.625 0.625 -616 0.625 0.625 0.75 -617 0.625 0.625 0.875 -618 0.625 0.75 0.125 -619 0.625 0.75 0.25 -620 0.625 0.75 0.375 -621 0.625 0.75 0.5 -622 0.625 0.75 0.625 -623 0.625 0.75 0.75 -624 0.625 0.75 0.875 -625 0.625 0.875 0.125 -626 0.625 0.875 0.25 -627 0.625 0.875 0.375 -628 0.625 0.875 0.5 -629 0.625 0.875 0.625 -630 0.625 0.875 0.75 -631 0.625 0.875 0.875 -632 0.75 0.125 0.125 -633 0.75 0.125 0.25 -634 0.75 0.125 0.375 -635 0.75 0.125 0.5 -636 0.75 0.125 0.625 -637 0.75 0.125 0.75 -638 0.75 0.125 0.875 -639 0.75 0.25 0.125 -640 0.75 0.25 0.25 -641 0.75 0.25 0.375 -642 0.75 0.25 0.5 -643 0.75 0.25 0.625 -644 0.75 0.25 0.75 -645 0.75 0.25 0.875 -646 0.75 0.375 0.125 -647 0.75 0.375 0.25 -648 0.75 0.375 0.375 -649 0.75 0.375 0.5 -650 0.75 0.375 0.625 -651 0.75 0.375 0.75 -652 0.75 0.375 0.875 -653 0.75 0.5 0.125 -654 0.75 0.5 0.25 -655 0.75 0.5 0.375 -656 0.75 0.5 0.5 -657 0.75 0.5 0.625 -658 0.75 0.5 0.75 -659 0.75 0.5 0.875 -660 0.75 0.625 0.125 -661 0.75 0.625 0.25 -662 0.75 0.625 0.375 -663 0.75 0.625 0.5 -664 0.75 0.625 0.625 -665 0.75 0.625 0.75 -666 0.75 0.625 0.875 -667 0.75 0.75 0.125 -668 0.75 0.75 0.25 -669 0.75 0.75 0.375 -670 0.75 0.75 0.5 -671 0.75 0.75 0.625 -672 0.75 0.75 0.75 -673 0.75 0.75 0.875 -674 0.75 0.875 0.125 -675 0.75 0.875 0.25 -676 0.75 0.875 0.375 -677 0.75 0.875 0.5 -678 0.75 0.875 0.625 -679 0.75 0.875 0.75 -680 0.75 0.875 0.875 -681 0.875 0.125 0.125 -682 0.875 0.125 0.25 -683 0.875 0.125 0.375 -684 0.875 0.125 0.5 -685 0.875 0.125 0.625 -686 0.875 0.125 0.75 -687 0.875 0.125 0.875 -688 0.875 0.25 0.125 -689 0.875 0.25 0.25 -690 0.875 0.25 0.375 -691 0.875 0.25 0.5 -692 0.875 0.25 0.625 -693 0.875 0.25 0.75 -694 0.875 0.25 0.875 -695 0.875 0.375 0.125 -696 0.875 0.375 0.25 -697 0.875 0.375 0.375 -698 0.875 0.375 0.5 -699 0.875 0.375 0.625 -700 0.875 0.375 0.75 -701 0.875 0.375 0.875 -702 0.875 0.5 0.125 -703 0.875 0.5 0.25 -704 0.875 0.5 0.375 -705 0.875 0.5 0.5 -706 0.875 0.5 0.625 -707 0.875 0.5 0.75 -708 0.875 0.5 0.875 -709 0.875 0.625 0.125 -710 0.875 0.625 0.25 -711 0.875 0.625 0.375 -712 0.875 0.625 0.5 -713 0.875 0.625 0.625 -714 0.875 0.625 0.75 -715 0.875 0.625 0.875 -716 0.875 0.75 0.125 -717 0.875 0.75 0.25 -718 0.875 0.75 0.375 -719 0.875 0.75 0.5 -720 0.875 0.75 0.625 -721 0.875 0.75 0.75 -722 0.875 0.75 0.875 -723 0.875 0.875 0.125 -724 0.875 0.875 0.25 -725 0.875 0.875 0.375 -726 0.875 0.875 0.5 -727 0.875 0.875 0.625 -728 0.875 0.875 0.75 -729 0.875 0.875 0.875 -$EndNodes -$Elements -512 -1 5 0 2 3 4 1 82 387 330 83 -2 5 0 82 387 330 83 84 388 331 85 -3 5 0 84 388 331 85 86 389 332 87 -4 5 0 86 389 332 87 88 390 333 89 -5 5 0 88 390 333 89 90 391 334 91 -6 5 0 90 391 334 91 92 392 335 93 -7 5 0 92 392 335 93 94 393 336 95 -8 5 0 94 393 336 95 96 338 337 97 -9 5 0 3 5 6 4 387 394 322 330 -10 5 0 387 394 322 330 388 395 323 331 -11 5 0 388 395 323 331 389 396 324 332 -12 5 0 389 396 324 332 390 397 325 333 -13 5 0 390 397 325 333 391 398 326 334 -14 5 0 391 398 326 334 392 399 327 335 -15 5 0 392 399 327 335 393 400 328 336 -16 5 0 393 400 328 336 338 339 329 337 -17 5 0 5 7 8 6 394 401 314 322 -18 5 0 394 401 314 322 395 402 315 323 -19 5 0 395 402 315 323 396 403 316 324 -20 5 0 396 403 316 324 397 404 317 325 -21 5 0 397 404 317 325 398 405 318 326 -22 5 0 398 405 318 326 399 406 319 327 -23 5 0 399 406 319 327 400 407 320 328 -24 5 0 400 407 320 328 339 340 321 329 -25 5 0 7 9 10 8 401 408 306 314 -26 5 0 401 408 306 314 402 409 307 315 -27 5 0 402 409 307 315 403 410 308 316 -28 5 0 403 410 308 316 404 411 309 317 -29 5 0 404 411 309 317 405 412 310 318 -30 5 0 405 412 310 318 406 413 311 319 -31 5 0 406 413 311 319 407 414 312 320 -32 5 0 407 414 312 320 340 341 313 321 -33 5 0 9 11 12 10 408 415 298 306 -34 5 0 408 415 298 306 409 416 299 307 -35 5 0 409 416 299 307 410 417 300 308 -36 5 0 410 417 300 308 411 418 301 309 -37 5 0 411 418 301 309 412 419 302 310 -38 5 0 412 419 302 310 413 420 303 311 -39 5 0 413 420 303 311 414 421 304 312 -40 5 0 414 421 304 312 341 342 305 313 -41 5 0 11 13 14 12 415 422 290 298 -42 5 0 415 422 290 298 416 423 291 299 -43 5 0 416 423 291 299 417 424 292 300 -44 5 0 417 424 292 300 418 425 293 301 -45 5 0 418 425 293 301 419 426 294 302 -46 5 0 419 426 294 302 420 427 295 303 -47 5 0 420 427 295 303 421 428 296 304 -48 5 0 421 428 296 304 342 343 297 305 -49 5 0 13 15 16 14 422 429 282 290 -50 5 0 422 429 282 290 423 430 283 291 -51 5 0 423 430 283 291 424 431 284 292 -52 5 0 424 431 284 292 425 432 285 293 -53 5 0 425 432 285 293 426 433 286 294 -54 5 0 426 433 286 294 427 434 287 295 -55 5 0 427 434 287 295 428 435 288 296 -56 5 0 428 435 288 296 343 344 289 297 -57 5 0 15 17 18 16 429 266 274 282 -58 5 0 429 266 274 282 430 267 275 283 -59 5 0 430 267 275 283 431 268 276 284 -60 5 0 431 268 276 284 432 269 277 285 -61 5 0 432 269 277 285 433 270 278 286 -62 5 0 433 270 278 286 434 271 279 287 -63 5 0 434 271 279 287 435 272 280 288 -64 5 0 435 272 280 288 344 273 281 289 -65 5 0 2 19 20 3 82 98 436 387 -66 5 0 82 98 436 387 84 99 437 388 -67 5 0 84 99 437 388 86 100 438 389 -68 5 0 86 100 438 389 88 101 439 390 -69 5 0 88 101 439 390 90 102 440 391 -70 5 0 90 102 440 391 92 103 441 392 -71 5 0 92 103 441 392 94 104 442 393 -72 5 0 94 104 442 393 96 105 345 338 -73 5 0 3 20 21 5 387 436 443 394 -74 5 0 387 436 443 394 388 437 444 395 -75 5 0 388 437 444 395 389 438 445 396 -76 5 0 389 438 445 396 390 439 446 397 -77 5 0 390 439 446 397 391 440 447 398 -78 5 0 391 440 447 398 392 441 448 399 -79 5 0 392 441 448 399 393 442 449 400 -80 5 0 393 442 449 400 338 345 346 339 -81 5 0 5 21 22 7 394 443 450 401 -82 5 0 394 443 450 401 395 444 451 402 -83 5 0 395 444 451 402 396 445 452 403 -84 5 0 396 445 452 403 397 446 453 404 -85 5 0 397 446 453 404 398 447 454 405 -86 5 0 398 447 454 405 399 448 455 406 -87 5 0 399 448 455 406 400 449 456 407 -88 5 0 400 449 456 407 339 346 347 340 -89 5 0 7 22 23 9 401 450 457 408 -90 5 0 401 450 457 408 402 451 458 409 -91 5 0 402 451 458 409 403 452 459 410 -92 5 0 403 452 459 410 404 453 460 411 -93 5 0 404 453 460 411 405 454 461 412 -94 5 0 405 454 461 412 406 455 462 413 -95 5 0 406 455 462 413 407 456 463 414 -96 5 0 407 456 463 414 340 347 348 341 -97 5 0 9 23 24 11 408 457 464 415 -98 5 0 408 457 464 415 409 458 465 416 -99 5 0 409 458 465 416 410 459 466 417 -100 5 0 410 459 466 417 411 460 467 418 -101 5 0 411 460 467 418 412 461 468 419 -102 5 0 412 461 468 419 413 462 469 420 -103 5 0 413 462 469 420 414 463 470 421 -104 5 0 414 463 470 421 341 348 349 342 -105 5 0 11 24 25 13 415 464 471 422 -106 5 0 415 464 471 422 416 465 472 423 -107 5 0 416 465 472 423 417 466 473 424 -108 5 0 417 466 473 424 418 467 474 425 -109 5 0 418 467 474 425 419 468 475 426 -110 5 0 419 468 475 426 420 469 476 427 -111 5 0 420 469 476 427 421 470 477 428 -112 5 0 421 470 477 428 342 349 350 343 -113 5 0 13 25 26 15 422 471 478 429 -114 5 0 422 471 478 429 423 472 479 430 -115 5 0 423 472 479 430 424 473 480 431 -116 5 0 424 473 480 431 425 474 481 432 -117 5 0 425 474 481 432 426 475 482 433 -118 5 0 426 475 482 433 427 476 483 434 -119 5 0 427 476 483 434 428 477 484 435 -120 5 0 428 477 484 435 343 350 351 344 -121 5 0 15 26 27 17 429 478 258 266 -122 5 0 429 478 258 266 430 479 259 267 -123 5 0 430 479 259 267 431 480 260 268 -124 5 0 431 480 260 268 432 481 261 269 -125 5 0 432 481 261 269 433 482 262 270 -126 5 0 433 482 262 270 434 483 263 271 -127 5 0 434 483 263 271 435 484 264 272 -128 5 0 435 484 264 272 344 351 265 273 -129 5 0 19 28 29 20 98 106 485 436 -130 5 0 98 106 485 436 99 107 486 437 -131 5 0 99 107 486 437 100 108 487 438 -132 5 0 100 108 487 438 101 109 488 439 -133 5 0 101 109 488 439 102 110 489 440 -134 5 0 102 110 489 440 103 111 490 441 -135 5 0 103 111 490 441 104 112 491 442 -136 5 0 104 112 491 442 105 113 352 345 -137 5 0 20 29 30 21 436 485 492 443 -138 5 0 436 485 492 443 437 486 493 444 -139 5 0 437 486 493 444 438 487 494 445 -140 5 0 438 487 494 445 439 488 495 446 -141 5 0 439 488 495 446 440 489 496 447 -142 5 0 440 489 496 447 441 490 497 448 -143 5 0 441 490 497 448 442 491 498 449 -144 5 0 442 491 498 449 345 352 353 346 -145 5 0 21 30 31 22 443 492 499 450 -146 5 0 443 492 499 450 444 493 500 451 -147 5 0 444 493 500 451 445 494 501 452 -148 5 0 445 494 501 452 446 495 502 453 -149 5 0 446 495 502 453 447 496 503 454 -150 5 0 447 496 503 454 448 497 504 455 -151 5 0 448 497 504 455 449 498 505 456 -152 5 0 449 498 505 456 346 353 354 347 -153 5 0 22 31 32 23 450 499 506 457 -154 5 0 450 499 506 457 451 500 507 458 -155 5 0 451 500 507 458 452 501 508 459 -156 5 0 452 501 508 459 453 502 509 460 -157 5 0 453 502 509 460 454 503 510 461 -158 5 0 454 503 510 461 455 504 511 462 -159 5 0 455 504 511 462 456 505 512 463 -160 5 0 456 505 512 463 347 354 355 348 -161 5 0 23 32 33 24 457 506 513 464 -162 5 0 457 506 513 464 458 507 514 465 -163 5 0 458 507 514 465 459 508 515 466 -164 5 0 459 508 515 466 460 509 516 467 -165 5 0 460 509 516 467 461 510 517 468 -166 5 0 461 510 517 468 462 511 518 469 -167 5 0 462 511 518 469 463 512 519 470 -168 5 0 463 512 519 470 348 355 356 349 -169 5 0 24 33 34 25 464 513 520 471 -170 5 0 464 513 520 471 465 514 521 472 -171 5 0 465 514 521 472 466 515 522 473 -172 5 0 466 515 522 473 467 516 523 474 -173 5 0 467 516 523 474 468 517 524 475 -174 5 0 468 517 524 475 469 518 525 476 -175 5 0 469 518 525 476 470 519 526 477 -176 5 0 470 519 526 477 349 356 357 350 -177 5 0 25 34 35 26 471 520 527 478 -178 5 0 471 520 527 478 472 521 528 479 -179 5 0 472 521 528 479 473 522 529 480 -180 5 0 473 522 529 480 474 523 530 481 -181 5 0 474 523 530 481 475 524 531 482 -182 5 0 475 524 531 482 476 525 532 483 -183 5 0 476 525 532 483 477 526 533 484 -184 5 0 477 526 533 484 350 357 358 351 -185 5 0 26 35 36 27 478 527 250 258 -186 5 0 478 527 250 258 479 528 251 259 -187 5 0 479 528 251 259 480 529 252 260 -188 5 0 480 529 252 260 481 530 253 261 -189 5 0 481 530 253 261 482 531 254 262 -190 5 0 482 531 254 262 483 532 255 263 -191 5 0 483 532 255 263 484 533 256 264 -192 5 0 484 533 256 264 351 358 257 265 -193 5 0 28 37 38 29 106 114 534 485 -194 5 0 106 114 534 485 107 115 535 486 -195 5 0 107 115 535 486 108 116 536 487 -196 5 0 108 116 536 487 109 117 537 488 -197 5 0 109 117 537 488 110 118 538 489 -198 5 0 110 118 538 489 111 119 539 490 -199 5 0 111 119 539 490 112 120 540 491 -200 5 0 112 120 540 491 113 121 359 352 -201 5 0 29 38 39 30 485 534 541 492 -202 5 0 485 534 541 492 486 535 542 493 -203 5 0 486 535 542 493 487 536 543 494 -204 5 0 487 536 543 494 488 537 544 495 -205 5 0 488 537 544 495 489 538 545 496 -206 5 0 489 538 545 496 490 539 546 497 -207 5 0 490 539 546 497 491 540 547 498 -208 5 0 491 540 547 498 352 359 360 353 -209 5 0 30 39 40 31 492 541 548 499 -210 5 0 492 541 548 499 493 542 549 500 -211 5 0 493 542 549 500 494 543 550 501 -212 5 0 494 543 550 501 495 544 551 502 -213 5 0 495 544 551 502 496 545 552 503 -214 5 0 496 545 552 503 497 546 553 504 -215 5 0 497 546 553 504 498 547 554 505 -216 5 0 498 547 554 505 353 360 361 354 -217 5 0 31 40 41 32 499 548 555 506 -218 5 0 499 548 555 506 500 549 556 507 -219 5 0 500 549 556 507 501 550 557 508 -220 5 0 501 550 557 508 502 551 558 509 -221 5 0 502 551 558 509 503 552 559 510 -222 5 0 503 552 559 510 504 553 560 511 -223 5 0 504 553 560 511 505 554 561 512 -224 5 0 505 554 561 512 354 361 362 355 -225 5 0 32 41 42 33 506 555 562 513 -226 5 0 506 555 562 513 507 556 563 514 -227 5 0 507 556 563 514 508 557 564 515 -228 5 0 508 557 564 515 509 558 565 516 -229 5 0 509 558 565 516 510 559 566 517 -230 5 0 510 559 566 517 511 560 567 518 -231 5 0 511 560 567 518 512 561 568 519 -232 5 0 512 561 568 519 355 362 363 356 -233 5 0 33 42 43 34 513 562 569 520 -234 5 0 513 562 569 520 514 563 570 521 -235 5 0 514 563 570 521 515 564 571 522 -236 5 0 515 564 571 522 516 565 572 523 -237 5 0 516 565 572 523 517 566 573 524 -238 5 0 517 566 573 524 518 567 574 525 -239 5 0 518 567 574 525 519 568 575 526 -240 5 0 519 568 575 526 356 363 364 357 -241 5 0 34 43 44 35 520 569 576 527 -242 5 0 520 569 576 527 521 570 577 528 -243 5 0 521 570 577 528 522 571 578 529 -244 5 0 522 571 578 529 523 572 579 530 -245 5 0 523 572 579 530 524 573 580 531 -246 5 0 524 573 580 531 525 574 581 532 -247 5 0 525 574 581 532 526 575 582 533 -248 5 0 526 575 582 533 357 364 365 358 -249 5 0 35 44 45 36 527 576 242 250 -250 5 0 527 576 242 250 528 577 243 251 -251 5 0 528 577 243 251 529 578 244 252 -252 5 0 529 578 244 252 530 579 245 253 -253 5 0 530 579 245 253 531 580 246 254 -254 5 0 531 580 246 254 532 581 247 255 -255 5 0 532 581 247 255 533 582 248 256 -256 5 0 533 582 248 256 358 365 249 257 -257 5 0 37 46 47 38 114 122 583 534 -258 5 0 114 122 583 534 115 123 584 535 -259 5 0 115 123 584 535 116 124 585 536 -260 5 0 116 124 585 536 117 125 586 537 -261 5 0 117 125 586 537 118 126 587 538 -262 5 0 118 126 587 538 119 127 588 539 -263 5 0 119 127 588 539 120 128 589 540 -264 5 0 120 128 589 540 121 129 366 359 -265 5 0 38 47 48 39 534 583 590 541 -266 5 0 534 583 590 541 535 584 591 542 -267 5 0 535 584 591 542 536 585 592 543 -268 5 0 536 585 592 543 537 586 593 544 -269 5 0 537 586 593 544 538 587 594 545 -270 5 0 538 587 594 545 539 588 595 546 -271 5 0 539 588 595 546 540 589 596 547 -272 5 0 540 589 596 547 359 366 367 360 -273 5 0 39 48 49 40 541 590 597 548 -274 5 0 541 590 597 548 542 591 598 549 -275 5 0 542 591 598 549 543 592 599 550 -276 5 0 543 592 599 550 544 593 600 551 -277 5 0 544 593 600 551 545 594 601 552 -278 5 0 545 594 601 552 546 595 602 553 -279 5 0 546 595 602 553 547 596 603 554 -280 5 0 547 596 603 554 360 367 368 361 -281 5 0 40 49 50 41 548 597 604 555 -282 5 0 548 597 604 555 549 598 605 556 -283 5 0 549 598 605 556 550 599 606 557 -284 5 0 550 599 606 557 551 600 607 558 -285 5 0 551 600 607 558 552 601 608 559 -286 5 0 552 601 608 559 553 602 609 560 -287 5 0 553 602 609 560 554 603 610 561 -288 5 0 554 603 610 561 361 368 369 362 -289 5 0 41 50 51 42 555 604 611 562 -290 5 0 555 604 611 562 556 605 612 563 -291 5 0 556 605 612 563 557 606 613 564 -292 5 0 557 606 613 564 558 607 614 565 -293 5 0 558 607 614 565 559 608 615 566 -294 5 0 559 608 615 566 560 609 616 567 -295 5 0 560 609 616 567 561 610 617 568 -296 5 0 561 610 617 568 362 369 370 363 -297 5 0 42 51 52 43 562 611 618 569 -298 5 0 562 611 618 569 563 612 619 570 -299 5 0 563 612 619 570 564 613 620 571 -300 5 0 564 613 620 571 565 614 621 572 -301 5 0 565 614 621 572 566 615 622 573 -302 5 0 566 615 622 573 567 616 623 574 -303 5 0 567 616 623 574 568 617 624 575 -304 5 0 568 617 624 575 363 370 371 364 -305 5 0 43 52 53 44 569 618 625 576 -306 5 0 569 618 625 576 570 619 626 577 -307 5 0 570 619 626 577 571 620 627 578 -308 5 0 571 620 627 578 572 621 628 579 -309 5 0 572 621 628 579 573 622 629 580 -310 5 0 573 622 629 580 574 623 630 581 -311 5 0 574 623 630 581 575 624 631 582 -312 5 0 575 624 631 582 364 371 372 365 -313 5 0 44 53 54 45 576 625 234 242 -314 5 0 576 625 234 242 577 626 235 243 -315 5 0 577 626 235 243 578 627 236 244 -316 5 0 578 627 236 244 579 628 237 245 -317 5 0 579 628 237 245 580 629 238 246 -318 5 0 580 629 238 246 581 630 239 247 -319 5 0 581 630 239 247 582 631 240 248 -320 5 0 582 631 240 248 365 372 241 249 -321 5 0 46 55 56 47 122 130 632 583 -322 5 0 122 130 632 583 123 131 633 584 -323 5 0 123 131 633 584 124 132 634 585 -324 5 0 124 132 634 585 125 133 635 586 -325 5 0 125 133 635 586 126 134 636 587 -326 5 0 126 134 636 587 127 135 637 588 -327 5 0 127 135 637 588 128 136 638 589 -328 5 0 128 136 638 589 129 137 373 366 -329 5 0 47 56 57 48 583 632 639 590 -330 5 0 583 632 639 590 584 633 640 591 -331 5 0 584 633 640 591 585 634 641 592 -332 5 0 585 634 641 592 586 635 642 593 -333 5 0 586 635 642 593 587 636 643 594 -334 5 0 587 636 643 594 588 637 644 595 -335 5 0 588 637 644 595 589 638 645 596 -336 5 0 589 638 645 596 366 373 374 367 -337 5 0 48 57 58 49 590 639 646 597 -338 5 0 590 639 646 597 591 640 647 598 -339 5 0 591 640 647 598 592 641 648 599 -340 5 0 592 641 648 599 593 642 649 600 -341 5 0 593 642 649 600 594 643 650 601 -342 5 0 594 643 650 601 595 644 651 602 -343 5 0 595 644 651 602 596 645 652 603 -344 5 0 596 645 652 603 367 374 375 368 -345 5 0 49 58 59 50 597 646 653 604 -346 5 0 597 646 653 604 598 647 654 605 -347 5 0 598 647 654 605 599 648 655 606 -348 5 0 599 648 655 606 600 649 656 607 -349 5 0 600 649 656 607 601 650 657 608 -350 5 0 601 650 657 608 602 651 658 609 -351 5 0 602 651 658 609 603 652 659 610 -352 5 0 603 652 659 610 368 375 376 369 -353 5 0 50 59 60 51 604 653 660 611 -354 5 0 604 653 660 611 605 654 661 612 -355 5 0 605 654 661 612 606 655 662 613 -356 5 0 606 655 662 613 607 656 663 614 -357 5 0 607 656 663 614 608 657 664 615 -358 5 0 608 657 664 615 609 658 665 616 -359 5 0 609 658 665 616 610 659 666 617 -360 5 0 610 659 666 617 369 376 377 370 -361 5 0 51 60 61 52 611 660 667 618 -362 5 0 611 660 667 618 612 661 668 619 -363 5 0 612 661 668 619 613 662 669 620 -364 5 0 613 662 669 620 614 663 670 621 -365 5 0 614 663 670 621 615 664 671 622 -366 5 0 615 664 671 622 616 665 672 623 -367 5 0 616 665 672 623 617 666 673 624 -368 5 0 617 666 673 624 370 377 378 371 -369 5 0 52 61 62 53 618 667 674 625 -370 5 0 618 667 674 625 619 668 675 626 -371 5 0 619 668 675 626 620 669 676 627 -372 5 0 620 669 676 627 621 670 677 628 -373 5 0 621 670 677 628 622 671 678 629 -374 5 0 622 671 678 629 623 672 679 630 -375 5 0 623 672 679 630 624 673 680 631 -376 5 0 624 673 680 631 371 378 379 372 -377 5 0 53 62 63 54 625 674 226 234 -378 5 0 625 674 226 234 626 675 227 235 -379 5 0 626 675 227 235 627 676 228 236 -380 5 0 627 676 228 236 628 677 229 237 -381 5 0 628 677 229 237 629 678 230 238 -382 5 0 629 678 230 238 630 679 231 239 -383 5 0 630 679 231 239 631 680 232 240 -384 5 0 631 680 232 240 372 379 233 241 -385 5 0 55 64 65 56 130 138 681 632 -386 5 0 130 138 681 632 131 139 682 633 -387 5 0 131 139 682 633 132 140 683 634 -388 5 0 132 140 683 634 133 141 684 635 -389 5 0 133 141 684 635 134 142 685 636 -390 5 0 134 142 685 636 135 143 686 637 -391 5 0 135 143 686 637 136 144 687 638 -392 5 0 136 144 687 638 137 145 380 373 -393 5 0 56 65 66 57 632 681 688 639 -394 5 0 632 681 688 639 633 682 689 640 -395 5 0 633 682 689 640 634 683 690 641 -396 5 0 634 683 690 641 635 684 691 642 -397 5 0 635 684 691 642 636 685 692 643 -398 5 0 636 685 692 643 637 686 693 644 -399 5 0 637 686 693 644 638 687 694 645 -400 5 0 638 687 694 645 373 380 381 374 -401 5 0 57 66 67 58 639 688 695 646 -402 5 0 639 688 695 646 640 689 696 647 -403 5 0 640 689 696 647 641 690 697 648 -404 5 0 641 690 697 648 642 691 698 649 -405 5 0 642 691 698 649 643 692 699 650 -406 5 0 643 692 699 650 644 693 700 651 -407 5 0 644 693 700 651 645 694 701 652 -408 5 0 645 694 701 652 374 381 382 375 -409 5 0 58 67 68 59 646 695 702 653 -410 5 0 646 695 702 653 647 696 703 654 -411 5 0 647 696 703 654 648 697 704 655 -412 5 0 648 697 704 655 649 698 705 656 -413 5 0 649 698 705 656 650 699 706 657 -414 5 0 650 699 706 657 651 700 707 658 -415 5 0 651 700 707 658 652 701 708 659 -416 5 0 652 701 708 659 375 382 383 376 -417 5 0 59 68 69 60 653 702 709 660 -418 5 0 653 702 709 660 654 703 710 661 -419 5 0 654 703 710 661 655 704 711 662 -420 5 0 655 704 711 662 656 705 712 663 -421 5 0 656 705 712 663 657 706 713 664 -422 5 0 657 706 713 664 658 707 714 665 -423 5 0 658 707 714 665 659 708 715 666 -424 5 0 659 708 715 666 376 383 384 377 -425 5 0 60 69 70 61 660 709 716 667 -426 5 0 660 709 716 667 661 710 717 668 -427 5 0 661 710 717 668 662 711 718 669 -428 5 0 662 711 718 669 663 712 719 670 -429 5 0 663 712 719 670 664 713 720 671 -430 5 0 664 713 720 671 665 714 721 672 -431 5 0 665 714 721 672 666 715 722 673 -432 5 0 666 715 722 673 377 384 385 378 -433 5 0 61 70 71 62 667 716 723 674 -434 5 0 667 716 723 674 668 717 724 675 -435 5 0 668 717 724 675 669 718 725 676 -436 5 0 669 718 725 676 670 719 726 677 -437 5 0 670 719 726 677 671 720 727 678 -438 5 0 671 720 727 678 672 721 728 679 -439 5 0 672 721 728 679 673 722 729 680 -440 5 0 673 722 729 680 378 385 386 379 -441 5 0 62 71 72 63 674 723 218 226 -442 5 0 674 723 218 226 675 724 219 227 -443 5 0 675 724 219 227 676 725 220 228 -444 5 0 676 725 220 228 677 726 221 229 -445 5 0 677 726 221 229 678 727 222 230 -446 5 0 678 727 222 230 679 728 223 231 -447 5 0 679 728 223 231 680 729 224 232 -448 5 0 680 729 224 232 379 386 225 233 -449 5 0 64 73 74 65 138 146 154 681 -450 5 0 138 146 154 681 139 147 155 682 -451 5 0 139 147 155 682 140 148 156 683 -452 5 0 140 148 156 683 141 149 157 684 -453 5 0 141 149 157 684 142 150 158 685 -454 5 0 142 150 158 685 143 151 159 686 -455 5 0 143 151 159 686 144 152 160 687 -456 5 0 144 152 160 687 145 153 161 380 -457 5 0 65 74 75 66 681 154 162 688 -458 5 0 681 154 162 688 682 155 163 689 -459 5 0 682 155 163 689 683 156 164 690 -460 5 0 683 156 164 690 684 157 165 691 -461 5 0 684 157 165 691 685 158 166 692 -462 5 0 685 158 166 692 686 159 167 693 -463 5 0 686 159 167 693 687 160 168 694 -464 5 0 687 160 168 694 380 161 169 381 -465 5 0 66 75 76 67 688 162 170 695 -466 5 0 688 162 170 695 689 163 171 696 -467 5 0 689 163 171 696 690 164 172 697 -468 5 0 690 164 172 697 691 165 173 698 -469 5 0 691 165 173 698 692 166 174 699 -470 5 0 692 166 174 699 693 167 175 700 -471 5 0 693 167 175 700 694 168 176 701 -472 5 0 694 168 176 701 381 169 177 382 -473 5 0 67 76 77 68 695 170 178 702 -474 5 0 695 170 178 702 696 171 179 703 -475 5 0 696 171 179 703 697 172 180 704 -476 5 0 697 172 180 704 698 173 181 705 -477 5 0 698 173 181 705 699 174 182 706 -478 5 0 699 174 182 706 700 175 183 707 -479 5 0 700 175 183 707 701 176 184 708 -480 5 0 701 176 184 708 382 177 185 383 -481 5 0 68 77 78 69 702 178 186 709 -482 5 0 702 178 186 709 703 179 187 710 -483 5 0 703 179 187 710 704 180 188 711 -484 5 0 704 180 188 711 705 181 189 712 -485 5 0 705 181 189 712 706 182 190 713 -486 5 0 706 182 190 713 707 183 191 714 -487 5 0 707 183 191 714 708 184 192 715 -488 5 0 708 184 192 715 383 185 193 384 -489 5 0 69 78 79 70 709 186 194 716 -490 5 0 709 186 194 716 710 187 195 717 -491 5 0 710 187 195 717 711 188 196 718 -492 5 0 711 188 196 718 712 189 197 719 -493 5 0 712 189 197 719 713 190 198 720 -494 5 0 713 190 198 720 714 191 199 721 -495 5 0 714 191 199 721 715 192 200 722 -496 5 0 715 192 200 722 384 193 201 385 -497 5 0 70 79 80 71 716 194 202 723 -498 5 0 716 194 202 723 717 195 203 724 -499 5 0 717 195 203 724 718 196 204 725 -500 5 0 718 196 204 725 719 197 205 726 -501 5 0 719 197 205 726 720 198 206 727 -502 5 0 720 198 206 727 721 199 207 728 -503 5 0 721 199 207 728 722 200 208 729 -504 5 0 722 200 208 729 385 201 209 386 -505 5 0 71 80 81 72 723 202 210 218 -506 5 0 723 202 210 218 724 203 211 219 -507 5 0 724 203 211 219 725 204 212 220 -508 5 0 725 204 212 220 726 205 213 221 -509 5 0 726 205 213 221 727 206 214 222 -510 5 0 727 206 214 222 728 207 215 223 -511 5 0 728 207 215 223 729 208 216 224 -512 5 0 729 208 216 224 386 209 217 225 -$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/CMakeLists.txt b/test/sumfact/poisson/facedir-facemod-variation/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b7b2698ccd178d2ad4eb9d2563aa4516cba8e00 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/CMakeLists.txt @@ -0,0 +1,64 @@ +if(consistent-edge-orientation_FOUND) + dune_add_formcompiler_system_test(UFLFILE poisson_dg_only_skeletons_3d.ufl + BASENAME sumfact_poisson_dg_3d_facedir_facemod_variation + INIFILE sumfact_poisson_dg_3d_facedir_facemod_variation.mini + SOURCE sumfact_poisson_dg_3d_facedir_facemod_variation_driver.cc + ANALYZE_GRID + ) + + dune_add_formcompiler_system_test(UFLFILE poisson_dg_only_skeletons_3d.ufl + BASENAME sumfact_poisson_fastdg_3d_facedir_facemod_variation + INIFILE sumfact_poisson_fastdg_3d_facedir_facemod_variation.mini + SOURCE sumfact_poisson_fastdg_3d_facedir_facemod_variation_driver.cc + ANALYZE_GRID + ) + + + # This can be used to verify the results from the actual test. Make sure to + # adjust the gmsh file in the ini file! + + # dune_add_formcompiler_system_test(UFLFILE poisson_dg_only_skeletons_3d.ufl + # BASENAME poisson_dg_3d_facedir_facemod_variation + # INIFILE poisson_dg_3d_facedir_facemod_variation.mini + # SOURCE poisson_dg_3d_facedir_facemod_variation_driver.cc + # ANALYZE_GRID + # ) + + + dune_symlink_to_source_files(FILES grid_unstructured_00.msh) + dune_symlink_to_source_files(FILES grid_unstructured_01.msh) + dune_symlink_to_source_files(FILES grid_unstructured_02.msh) + dune_symlink_to_source_files(FILES grid_unstructured_03.msh) + dune_symlink_to_source_files(FILES grid_unstructured_04.msh) + dune_symlink_to_source_files(FILES grid_unstructured_05.msh) + dune_symlink_to_source_files(FILES grid_unstructured_06.msh) + dune_symlink_to_source_files(FILES grid_unstructured_07.msh) + dune_symlink_to_source_files(FILES grid_unstructured_08.msh) + dune_symlink_to_source_files(FILES grid_unstructured_09.msh) + dune_symlink_to_source_files(FILES grid_unstructured_10.msh) + dune_symlink_to_source_files(FILES grid_unstructured_11.msh) + dune_symlink_to_source_files(FILES grid_unstructured_12.msh) + dune_symlink_to_source_files(FILES grid_unstructured_13.msh) + dune_symlink_to_source_files(FILES grid_unstructured_14.msh) + dune_symlink_to_source_files(FILES grid_unstructured_15.msh) + dune_symlink_to_source_files(FILES grid_unstructured_16.msh) + dune_symlink_to_source_files(FILES grid_unstructured_17.msh) + dune_symlink_to_source_files(FILES grid_unstructured_18.msh) + dune_symlink_to_source_files(FILES grid_unstructured_19.msh) + dune_symlink_to_source_files(FILES grid_unstructured_20.msh) + dune_symlink_to_source_files(FILES grid_unstructured_21.msh) + dune_symlink_to_source_files(FILES grid_unstructured_22.msh) + dune_symlink_to_source_files(FILES grid_unstructured_23.msh) + dune_symlink_to_source_files(FILES grid_unstructured_24.msh) + dune_symlink_to_source_files(FILES grid_unstructured_25.msh) + dune_symlink_to_source_files(FILES grid_unstructured_26.msh) + dune_symlink_to_source_files(FILES grid_unstructured_27.msh) + dune_symlink_to_source_files(FILES grid_unstructured_28.msh) + dune_symlink_to_source_files(FILES grid_unstructured_29.msh) + dune_symlink_to_source_files(FILES grid_unstructured_30.msh) + dune_symlink_to_source_files(FILES grid_unstructured_31.msh) + dune_symlink_to_source_files(FILES grid_unstructured_32.msh) + dune_symlink_to_source_files(FILES grid_unstructured_33.msh) + dune_symlink_to_source_files(FILES grid_unstructured_34.msh) + dune_symlink_to_source_files(FILES grid_unstructured_35.msh) +endif() diff --git a/test/sumfact/poisson/facedir-facemod-variation/generate_meshfiles.py b/test/sumfact/poisson/facedir-facemod-variation/generate_meshfiles.py new file mode 100644 index 0000000000000000000000000000000000000000..dd27346e98128f31061f3d9acc4268f4410922c5 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/generate_meshfiles.py @@ -0,0 +1,113 @@ +"""This program can be used to generate the 36 msh files. It is not integrated +into the build system and needs to be called by hand. + +""" + +c0_0 = [2,1,7,8,5,4,10,11] +c0_1 = [1,2,5,4,7,8,11,10] +c0_2 = [2,5,4,1,8,11,10,7] +c0_3 = [1,7,8,2,4,10,11,5] +c0_4 = [2,8,11,5,1,7,10,4] +c0_5 = [1,4,10,7,2,5,11,8] + +c1_0 = [2,3,6,5,8,9,12,11] +c1_1 = [3,2,8,9,6,5,11,12] +c1_2 = [2,8,9,3,5,11,12,6] +c1_3 = [3,6,5,2,9,12,11,8] +c1_4 = [2,5,11,8,3,6,12,9] +c1_5 = [3,9,12,6,2,8,11,5] + +c0s = [c0_0, c0_1, c0_2, c0_3, c0_4, c0_5] +c1s = [c1_0, c1_1, c1_2, c1_3, c1_4, c1_5] + +begin_structured = """$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 0 0 0 +2 1 0 0 +3 2 0 0 +4 0 1 0 +5 1 1 0 +6 2 1 0 +7 0 0 1 +8 1 0 1 +9 2 0 1 +10 0 1 1 +11 1 1 1 +12 2 1 1 +$EndNodes +$Elements +2 +""" + +begin_affine = """$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 0.5 0 0 +2 1 1 1 +3 1.5 2 2 +4 0 1 0 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1 +8 0.5 0 2 +9 1 1 3 +10 -0.5 0 1 +11 0 1 2 +12 0.5 2 3 +$EndNodes +$Elements +2 +""" + +begin_unstructured = """$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +""" + + +end = """ +$EndElements +""" + + +def generate_files(name, begin): + from itertools import product + for i, c in enumerate(product(c0s, c1s)): + with open('{}_{}.msh'.format(name, str(i).zfill(2)), 'w+') as f: + f.write(begin) + f.write('1 5 0') + for a in c[0]: + f.write(' {}'.format(a)) + f.write('\n') + f.write('2 5 0') + for a in c[1]: + f.write(' {}'.format(a)) + + f.write(end) + + +# generate_files("grid_structure", begin_structured) +# generate_files("grid_affine", begin_affine) +generate_files("grid_unstructured", begin_unstructured) diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_00.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_00.msh new file mode 100644 index 0000000000000000000000000000000000000000..a1931e054c7f83b11a2e186d872934ea281303ae --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_00.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_01.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_01.msh new file mode 100644 index 0000000000000000000000000000000000000000..795eb9628e4de262e908099dc26d75d72bd3de12 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_01.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_02.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_02.msh new file mode 100644 index 0000000000000000000000000000000000000000..12d746cffb2245dd81405a602691998663bddc09 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_02.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_03.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_03.msh new file mode 100644 index 0000000000000000000000000000000000000000..b0973e4fad4307a5c1efee6a1120ff2c8c91eb17 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_03.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_04.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_04.msh new file mode 100644 index 0000000000000000000000000000000000000000..40404e0ac3b239a384da54b91582e0f742fa8606 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_04.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_05.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_05.msh new file mode 100644 index 0000000000000000000000000000000000000000..887f391bc7936088f2e570ee15a6c347da8d6fea --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_05.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 1 7 8 5 4 10 11 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_06.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_06.msh new file mode 100644 index 0000000000000000000000000000000000000000..7b55320fa6331c9460ced4dacd9daa08ccf6a1ef --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_06.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_07.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_07.msh new file mode 100644 index 0000000000000000000000000000000000000000..a4ca3e9f4cf3b742fe7be444fe8eecb587add74d --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_07.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_08.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_08.msh new file mode 100644 index 0000000000000000000000000000000000000000..0ae9d50d1072f21932119fe729e9928f4c7df248 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_08.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_09.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_09.msh new file mode 100644 index 0000000000000000000000000000000000000000..ffcd009146b01106bd957c03300650572e745cf4 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_09.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_10.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_10.msh new file mode 100644 index 0000000000000000000000000000000000000000..56490e7f4203461e1b2a0f80743c405d27daeaa5 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_10.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_11.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_11.msh new file mode 100644 index 0000000000000000000000000000000000000000..44d84a4031888a98e4e38500eda340e2760da6d1 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_11.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 2 5 4 7 8 11 10 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_12.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_12.msh new file mode 100644 index 0000000000000000000000000000000000000000..e0efb92d6a076be59a0658ec30f5494ed402b65a --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_12.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_13.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_13.msh new file mode 100644 index 0000000000000000000000000000000000000000..f853bacee70b191a00dd76ce53a9b214600c7c0c --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_13.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_14.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_14.msh new file mode 100644 index 0000000000000000000000000000000000000000..c50e279cd82defd7167bde7c5df76c4a1946c156 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_14.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_15.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_15.msh new file mode 100644 index 0000000000000000000000000000000000000000..72fa0582683c268dd84d9371b5dd8f7848067ff9 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_15.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_16.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_16.msh new file mode 100644 index 0000000000000000000000000000000000000000..150abced562777d07984c265f11a0ba85e4be81d --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_16.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_17.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_17.msh new file mode 100644 index 0000000000000000000000000000000000000000..23f40b31012b9490c9e56f622d8e51c35478f4d9 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_17.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 5 4 1 8 11 10 7 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_18.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_18.msh new file mode 100644 index 0000000000000000000000000000000000000000..2fe032274308884cb49b3804a4322cfb00d13fcb --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_18.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_19.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_19.msh new file mode 100644 index 0000000000000000000000000000000000000000..ac299fb06f05abc21df8cb1f8f42aeb852f657e6 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_19.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_20.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_20.msh new file mode 100644 index 0000000000000000000000000000000000000000..98d3d061e469fe08fb332b76475d0d0e90fdcaf2 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_20.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_21.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_21.msh new file mode 100644 index 0000000000000000000000000000000000000000..76bc6ae032808318061d7c0e1e0eeb4d7e775fa1 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_21.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_22.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_22.msh new file mode 100644 index 0000000000000000000000000000000000000000..dfaba29f17ca850f94da9b6c3b4b1f5e81711386 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_22.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_23.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_23.msh new file mode 100644 index 0000000000000000000000000000000000000000..df9d986f5862a712cb8535422698efd6949836a5 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_23.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 7 8 2 4 10 11 5 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_24.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_24.msh new file mode 100644 index 0000000000000000000000000000000000000000..c368d77672bdd1b02a2ca1965e28b11d9d16be74 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_24.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_25.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_25.msh new file mode 100644 index 0000000000000000000000000000000000000000..c9796b6d1a98d4a6224971fb1938d3bcba2cd4f9 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_25.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_26.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_26.msh new file mode 100644 index 0000000000000000000000000000000000000000..e625891083b9f64f1c789cc7710abc52845d4012 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_26.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_27.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_27.msh new file mode 100644 index 0000000000000000000000000000000000000000..f55ee89213b4206d67e1f2a0e15646fa69578f15 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_27.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_28.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_28.msh new file mode 100644 index 0000000000000000000000000000000000000000..cda6cb2126c2c51ffe290606740307169e923b61 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_28.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_29.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_29.msh new file mode 100644 index 0000000000000000000000000000000000000000..69f06e5d1597663a4e1f47af2b94b8a3e58fb272 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_29.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 2 8 11 5 1 7 10 4 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_30.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_30.msh new file mode 100644 index 0000000000000000000000000000000000000000..6a8d551d25fd954b83dc0e0739c746c07350a687 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_30.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 2 3 6 5 8 9 12 11 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_31.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_31.msh new file mode 100644 index 0000000000000000000000000000000000000000..9a15ada30328f7251e384741732d0a38e69f2dcb --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_31.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 3 2 8 9 6 5 11 12 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_32.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_32.msh new file mode 100644 index 0000000000000000000000000000000000000000..338871a6d9b191ed5ce0c8936b5e715ce7df87dd --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_32.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 2 8 9 3 5 11 12 6 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_33.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_33.msh new file mode 100644 index 0000000000000000000000000000000000000000..13939ddb9bab72ecafa150a096a624b6e7b1cbbd --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_33.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 3 6 5 2 9 12 11 8 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_34.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_34.msh new file mode 100644 index 0000000000000000000000000000000000000000..37c5e1fb7ba63111f7bedaede8fdddff99c03e25 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_34.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 2 5 11 8 3 6 12 9 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_35.msh b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_35.msh new file mode 100644 index 0000000000000000000000000000000000000000..a2f95b961a02094433de16e528f7671befada7be --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/grid_unstructured_35.msh @@ -0,0 +1,23 @@ +$MeshFormat +2.0 0 8 +$EndMeshFormat +$Nodes +12 +1 -0.5 0 -1 +2 1.2 1.1 1.1 +3 1.5 2 1.5 +4 -0.5 1.5 -0.5 +5 0.5 2 1 +6 1 3 2 +7 0 -1 1.5 +8 0.4 -0.1 1.8 +9 1 1 3 +10 -0.7 0.2 1.2 +11 0.1 1.3 2.2 +12 0.5 2.2 3.5 +$EndNodes +$Elements +2 +1 5 0 1 4 10 7 2 5 11 8 +2 5 0 3 9 12 6 2 8 11 5 +$EndElements diff --git a/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation.mini b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation.mini new file mode 100644 index 0000000000000000000000000000000000000000..45927298669692f8d3675e1d7896d565b922ae53 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation.mini @@ -0,0 +1,41 @@ +__name = poisson_dg_3d_facedir_facemod_variation_{__exec_suffix} +__exec_suffix = {deg_suffix}_{diff_suffix}_{quadvec_suffix}_{gradvec_suffix} + +diff_suffix = numdiff, symdiff | expand num +quadvec_suffix = quadvec, nonquadvec | expand quad +gradvec_suffix = gradvec, nongradvec | expand grad +deg_suffix = deg{formcompiler.ufl_variants.degree} + + +# Be careful when you adjust these as the driver is handwritten! +{deg_suffix} == deg2 | exclude +{diff_suffix} == numdiff | exclude +{quadvec_suffix} == quadvec | exclude +{gradvec_suffix} == gradvec | exclude + +## Structured +# cells = 2 1 1 +# extension = 2. 1. 1. +## Gmsh +gmshFile = grid_unstructured_06.msh +## Unstructured +# lowerleft = 0.0 0.0 0.0 +# upperright = 2.0 1.0 1.0 +# elements = 2 1 1 +# elementType = quadrilateral + +printresidual = 1 + +[formcompiler] +compare_l2errorsquared = 1e-4, 5e-6 | expand deg +debug_interpolate_input = 1 +grid_unstructured = 1 + +[formcompiler.r] +numerical_jacobian = 1, 0 | expand num +sumfact = 0 +vectorization_quadloop = 1, 0 | expand quad +vectorization_strategy = model, none | expand grad + +[formcompiler.ufl_variants] +degree = 1, 2 | expand deg diff --git a/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation_driver.cc b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation_driver.cc new file mode 100644 index 0000000000000000000000000000000000000000..2f8cc6c8614e0cdb954a52fa5de808dbff466b07 --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_3d_facedir_facemod_variation_driver.cc @@ -0,0 +1,238 @@ +#include "config.h" +#include "dune/common/parallel/mpihelper.hh" +#include "dune/pdelab/stationary/linearproblem.hh" +#include "dune/pdelab/backend/istl.hh" +#include "dune/grid/uggrid.hh" +#include "dune/grid/yaspgrid.hh" +#include "dune/pdelab/finiteelementmap/qkdg.hh" +#include "poisson_dg_3d_facedir_facemod_variation_deg1_symdiff_nonquadvec_nongradvec_rOperator_file.hh" +#include "dune/pdelab/gridoperator/gridoperator.hh" +#include "dune/testtools/gridconstruction.hh" +#include "dune/common/parametertree.hh" +#include "dune/common/parametertreeparser.hh" +#include "dune/consistent-edge-orientation/createconsistentgrid.hh" +#include <random> +#include "dune/pdelab/gridfunctionspace/vtk.hh" +#include "dune/grid/io/file/vtk/subsamplingvtkwriter.hh" +#include "string" +#include "dune/codegen/vtkpredicate.hh" +#include "dune/pdelab/function/callableadapter.hh" +#include "dune/pdelab/gridfunctionspace/gridfunctionadapter.hh" +#include "dune/pdelab/common/functionutilities.hh" + +template <typename T> +bool isclose(T a, T b, double rel_tol=1e-9, double abs_tol=0.0){ + // Basically a python isclose (PEP 485) without error checking... + return std::abs(a-b) <= std::max(rel_tol*std::max(std::abs(a), std::abs(b)), abs_tol); +} + +template<typename T> +bool fuzzy_is_permutation(T a, T b, double rel_tol=1e-9, double abs_tol=1e-14){ + assert (a.size()==b.size()); + std::sort(a.begin(), a.end()); + std::sort(b.begin(), b.end()); + + for (std::size_t i=0; i<a.size(); ++i){ + if (!isclose(a[i], b[i], rel_tol, abs_tol)) + return false; + } + return true; +} + + + +template<typename GV> +void test_grid(GV gv){ + // iterate over all entities of the grid + for (const auto& e : elements(gv)) + { + std::cout << "## New Element!" << std::endl; + auto geo = e.geometry(); + for (int i=0; i<geo.corners(); i++){ + auto global_corner = geo.corner(i); + auto local_corner = geo.local(global_corner); + std::cout << "global_corner: "; + for (int i=0; i<3; ++i) + std::cout << global_corner[i] << " "; + std::cout << std::endl; + } + for (int i=0; i<geo.corners(); i++){ + auto global_corner = geo.corner(i); + auto local_corner = geo.local(global_corner); + std::cout << "local_corner: "; + for (int i=0; i<3; ++i) + std::cout << local_corner[i] << " "; + std::cout << std::endl; + } + } +} + +int main(int argc, char** argv){ + try + { + // Initialize basic stuff... + Dune::MPIHelper& mpihelper = Dune::MPIHelper::instance(argc, argv); + using RangeType = double; + Dune::ParameterTree initree; + Dune::ParameterTreeParser::readINITree(argv[1], initree); + + // Setup grid (view)... + using Grid = Dune::UGGrid<3>; + // using Grid = Dune::ALUGrid<3,3,Dune::cube,Dune::nonconforming>; + + using GV = Grid::LeafGridView; + using DF = Grid::ctype; + + // Gmsh + IniGridFactory<Grid> factory(initree); + std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); + std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); + GV gv = grid->leafGridView(); + + test_grid(gv); + + // Set up finite element maps... + using DG1_FEM = Dune::PDELab::QkDGLocalFiniteElementMap<DF, RangeType, 1, 3>; + DG1_FEM dg1_fem; + + // Set up grid function spaces... + using VectorBackendDG1 = Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::none>; + using NoConstraintsAssembler = Dune::PDELab::NoConstraints; + using DG1_GFS = Dune::PDELab::GridFunctionSpace<GV, DG1_FEM, NoConstraintsAssembler, VectorBackendDG1>; + DG1_GFS dg1_gfs_(gv, dg1_fem); + dg1_gfs_.name("dg1_gfs_"); + + // Set up constraints container... + using DG1_GFS_CC = DG1_GFS::ConstraintsContainer<RangeType>::Type; + DG1_GFS_CC dg1_gfs__cc; + dg1_gfs__cc.clear(); + Dune::PDELab::constraints(dg1_gfs_, dg1_gfs__cc); + + // Set up grid grid operators... + using LOP_R = rOperator<DG1_GFS, DG1_GFS, RangeType>; + using MatrixBackend = Dune::PDELab::ISTL::BCRSMatrixBackend<>; + using GO_r = Dune::PDELab::GridOperator<DG1_GFS, DG1_GFS, LOP_R, MatrixBackend, DF, RangeType, RangeType, DG1_GFS_CC, DG1_GFS_CC>; + LOP_R lop_r(dg1_gfs_, dg1_gfs_, initree); + dg1_gfs_.update(); + int generic_dof_estimate = 8 * dg1_gfs_.maxLocalSize(); + int dofestimate = initree.get<int>("istl.number_of_nnz", generic_dof_estimate); + MatrixBackend mb(dofestimate); + GO_r go_r(dg1_gfs_, dg1_gfs__cc, dg1_gfs_, dg1_gfs__cc, lop_r, mb); + std::cout << "gfs with " << dg1_gfs_.size() << " dofs generated "<< std::endl; + std::cout << "cc with " << dg1_gfs__cc.size() << " dofs generated "<< std::endl; + + // Set up solution vectors... + using V_R = Dune::PDELab::Backend::Vector<DG1_GFS,DF>; + V_R x_r(dg1_gfs_); + x_r = 0.0; + auto lambda_0000 = [&](const auto& is, const auto& xl){ auto x=is.geometry().global(xl); return exp((-1.0) * ((0.5 - x[2]) * (0.5 - x[2]) + (0.5 - x[1]) * (0.5 - x[1]) + (0.5 - x[0]) * (0.5 - x[0])));; }; + auto func_0000 = Dune::PDELab::makeGridFunctionFromCallable(gv, lambda_0000); + + // Set up (non)linear solvers... + using LinearSolver = Dune::PDELab::ISTLBackend_SEQ_SuperLU; + using SLP = Dune::PDELab::StationaryLinearProblemSolver<GO_r, LinearSolver, V_R>; + LinearSolver ls(false); + double reduction = initree.get<double>("reduction", 1e-12); + SLP slp(go_r, ls, x_r, reduction); + // slp.apply(); + + // Do visualization... + using VTKWriter = Dune::SubsamplingVTKWriter<GV>; + Dune::RefinementIntervals subint(initree.get<int>("vtk.subsamplinglevel", 1)); + VTKWriter vtkwriter(gv, subint); + std::string vtkfile = initree.get<std::string>("wrapper.vtkcompare.name", "output"); + CuttingPredicate predicate; + Dune::PDELab::addSolutionToVTKWriter(vtkwriter, dg1_gfs_, x_r, Dune::PDELab::vtk::defaultNameScheme(), predicate); + vtkwriter.write(vtkfile, Dune::VTK::ascii); + + // Maybe print residuals and matrices to stdout... + if (initree.get<bool>("printresidual", false)) { + using Dune::PDELab::Backend::native; + V_R x_s(x_r); + // Interpolate input + auto interpolate_lambda = + [] (const auto& e, const auto& xl){ + auto xg = e.geometry().global(xl); + auto center = e.geometry().center(); + if (center.two_norm() < 2){ + return std::sin((xg.two_norm2()+xg[0]/3)/10); + } + else{ + return std::sin((xg.two_norm2())/10); + } + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_s); + Dune::printvector(std::cout, native(x_s), "x_s", "row"); + + V_R r(x_r); + r=0.0; + go_r.residual(x_s, r); + Dune::printvector(std::cout, native(r), "residual vector", "row"); + + // std::cout.precision(17); + std::vector<RangeType> residual(16); + for (std::size_t i=0; i<16; ++i){ + residual[i] = native(r)[i]; + } + std::cout << "Residual:" << std::endl; + std::cout.precision(17); + for (std::size_t i=0; i<16; ++i){ + std::cout << residual[i] << ", "; + } + std::cout << std::endl; + } + if (initree.get<bool>("printmatrix", false)) { + using Dune::PDELab::Backend::native; + V_R r(x_r); + // Interpolate input + auto interpolate_lambda = [] (const auto& x){ + return std::exp(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]); + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_r); + using M = typename GO_r::Traits::Jacobian; + M m(go_r); + go_r.jacobian(x_r,m); + using Dune::PDELab::Backend::native; + Dune::printmatrix(std::cout, native(m),"global stiffness matrix","row",9,1); + } + + // // Maybe calculate errors for test results... + // using DG1_GFS__DGF = Dune::PDELab::DiscreteGridFunction<decltype(dg1_gfs_),decltype(x_r)>; + // DG1_GFS__DGF dg1_gfs__dgf(dg1_gfs_,x_r); + // using DifferenceSquaredAdapter_ = Dune::PDELab::DifferenceSquaredAdapter<decltype(func_0000), decltype(dg1_gfs__dgf)>; + // DifferenceSquaredAdapter_ dsa_(func_0000, dg1_gfs__dgf); + // Dune::FieldVector<RangeType, 1> l2error(0.0); + // { + // // L2 error squared of difference between numerical + // // solution and the interpolation of exact solution + // // for treepath () + // typename decltype(dsa_)::Traits::RangeType err(0.0); + // Dune::PDELab::integrateGridFunction(dsa_, err, 10); + + // l2error += err; + // if (gv.comm().rank() == 0){ + // std::cout << "L2 Error for treepath : " << err << std::endl; + // }} + // bool testfail(false); + // using std::abs; + // using std::isnan; + // if (gv.comm().rank() == 0){ + // std::cout << "\nl2errorsquared: " << l2error << std::endl << std::endl; + // } + // if (isnan(l2error[0]) or abs(l2error[0])>1e-4) + // testfail = true; + // return testfail; + return 0; + + } + catch (Dune::Exception& e) + { std::cerr << "Dune reported error: " << e << std::endl; + return 1; + } + catch (std::exception& e) + { std::cerr << "Unknown exception thrown!" << std::endl; + return 1; + } +} diff --git a/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_only_skeletons_3d.ufl b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_only_skeletons_3d.ufl new file mode 100644 index 0000000000000000000000000000000000000000..98785a640583abbe9c409520923f4ff786a948fc --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/poisson_dg_only_skeletons_3d.ufl @@ -0,0 +1,51 @@ +cell = hexahedron +dim = 3 + +x = SpatialCoordinate(cell) +c = (0.5-x[0])**2 + (0.5-x[1])**2 + (0.5-x[2])**2 +g = exp(-1.*c) +f = 2*(3.-2*c)*g + +V = FiniteElement("DG", cell, degree) + +u = TrialFunction(V) +v = TestFunction(V) + +n = FacetNormal(cell)('+') + +# penalty factor +alpha = 1.0 + +# Note: Cell volume calculation by the MultiLinearGeometry is not accurate +# enough (bug). Until this is fixed we just use 1 for h since the test is +# synthetic anyway. +# h_ext = CellVolume(cell) / FacetArea(cell) +h_ext = 1 +gamma_ext = (alpha * degree * (degree + dim - 1)) / h_ext + +# Note: Cell volume calculation by the MultiLinearGeometry is not accurate +# enough (bug). Until this is fixed we just use 1 for h since the test is +# synthetic anyway. +# h_int = Min(CellVolume(cell)('+'), CellVolume(cell)('-')) / FacetArea(cell) +h_int = 1 +gamma_int = (alpha * degree * (degree + dim - 1)) / h_int + +# SIPG: -1.0, IIPG: 0.0, NIPG: 1.0 +theta = 1.0 + +# r = inner(grad(u), grad(v))*dx \ +# - f*v*dx \ +# - inner(n, avg(grad(u)))*jump(v)*dS \ +# + gamma_int*jump(u)*jump(v)*dS \ +# + theta*jump(u)*inner(avg(grad(v)), n)*dS \ +# - inner(n, grad(u))*v*ds \ +# + gamma_ext*u*v*ds \ +# + theta*u*inner(grad(v), n)*ds \ +# - gamma_ext*g*v*ds \ +# - theta*g*inner(grad(v), n)*ds + +r = - inner(n, avg(grad(u)))*jump(v)*dS \ + + gamma_int*jump(u)*jump(v)*dS \ + + theta*jump(u)*inner(avg(grad(v)), n)*dS + +exact_solution = g diff --git a/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation.mini b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation.mini new file mode 100644 index 0000000000000000000000000000000000000000..664421e4f91a3893c42783c209068e306b110c7e --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation.mini @@ -0,0 +1,49 @@ +__name = sumfact_poisson_dg_3d_facedir_facemod_variation_{__exec_suffix} +__exec_suffix = {deg_suffix}_{diff_suffix}_{quadvec_suffix}_{gradvec_suffix}_{msh_suffix} + +diff_suffix = numdiff, symdiff | expand num +quadvec_suffix = quadvec, nonquadvec | expand quad +gradvec_suffix = gradvec, nongradvec | expand grad +deg_suffix = deg{formcompiler.ufl_variants.degree} +msh_suffix = msh{msh_number} + + +# Be careful when you adjust these as the driver is handwritten! +{deg_suffix} == deg2 | exclude +{diff_suffix} == numdiff | exclude +{quadvec_suffix} == quadvec | exclude +# {gradvec_suffix} == gradvec | exclude + + +msh_number = 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 | expand +gmshFile = grid_unstructured_{msh_number}.msh +# gmshFile = grid_affine_{msh_number}.msh + +printresidual = 1 + + +[__static] +CLASSNAME = localoperator_{msh_suffix}_{gradvec_suffix} +MSH_VARIANT = {msh_number} | toint +GRADVEC = 1, 0 | expand grad + +[wrapper.vtkcompare] +name = {__name} +extension = vtu + +[formcompiler] +compare_l2errorsquared = 1e-4, 5e-6 | expand deg +grid_unstructured = 1 +debug_interpolate_input = 1 + +[formcompiler.r] +classname = {__static.CLASSNAME} +filename = sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_{msh_suffix}_{gradvec_suffix}.hh +numerical_jacobian = 1, 0 | expand num +sumfact = 1 +sumfact_regular_jacobians = 1 +vectorization_quadloop = 1, 0 | expand quad +vectorization_strategy = model, none | expand grad + +[formcompiler.ufl_variants] +degree = 1, 2 | expand deg diff --git a/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation_driver.cc b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation_driver.cc new file mode 100644 index 0000000000000000000000000000000000000000..4b57deaa50bc6e435b40dec8060d55e927797b2a --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_dg_3d_facedir_facemod_variation_driver.cc @@ -0,0 +1,389 @@ +#include "config.h" +#include "dune/common/parallel/mpihelper.hh" +#include "dune/pdelab/stationary/linearproblem.hh" +#include "dune/pdelab/backend/istl.hh" +#include "dune/grid/uggrid.hh" +#include "dune/grid/yaspgrid.hh" +#include "dune/pdelab/finiteelementmap/qkdg.hh" +#include "dune/pdelab/gridoperator/gridoperator.hh" +#include "dune/testtools/gridconstruction.hh" +#include "dune/common/parametertree.hh" +#include "dune/common/parametertreeparser.hh" +#include "dune/consistent-edge-orientation/createconsistentgrid.hh" +#include <random> +#include "dune/pdelab/gridfunctionspace/vtk.hh" +#include "dune/grid/io/file/vtk/subsamplingvtkwriter.hh" +#include "string" +#include "dune/codegen/vtkpredicate.hh" +#include "dune/pdelab/function/callableadapter.hh" +#include "dune/pdelab/gridfunctionspace/gridfunctionadapter.hh" +#include "dune/pdelab/common/functionutilities.hh" + +#if MSH_VARIANT == 0 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh00_nongradvec.hh" +#elif MSH_VARIANT == 1 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh01_nongradvec.hh" +#elif MSH_VARIANT == 2 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh02_nongradvec.hh" +#elif MSH_VARIANT == 3 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh03_nongradvec.hh" +#elif MSH_VARIANT == 4 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh04_nongradvec.hh" +#elif MSH_VARIANT == 5 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh05_nongradvec.hh" +#elif MSH_VARIANT == 6 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh06_nongradvec.hh" +#elif MSH_VARIANT == 7 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh07_nongradvec.hh" +#elif MSH_VARIANT == 8 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh08_nongradvec.hh" +#elif MSH_VARIANT == 9 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh09_nongradvec.hh" +#elif MSH_VARIANT == 10 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh10_nongradvec.hh" +#elif MSH_VARIANT == 11 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh11_nongradvec.hh" +#elif MSH_VARIANT == 12 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh12_nongradvec.hh" +#elif MSH_VARIANT == 13 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh13_nongradvec.hh" +#elif MSH_VARIANT == 14 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh14_nongradvec.hh" +#elif MSH_VARIANT == 15 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh15_nongradvec.hh" +#elif MSH_VARIANT == 16 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh16_nongradvec.hh" +#elif MSH_VARIANT == 17 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh17_nongradvec.hh" +#elif MSH_VARIANT == 18 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh18_nongradvec.hh" +#elif MSH_VARIANT == 19 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh19_nongradvec.hh" +#elif MSH_VARIANT == 20 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh20_nongradvec.hh" +#elif MSH_VARIANT == 21 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh21_nongradvec.hh" +#elif MSH_VARIANT == 22 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh22_nongradvec.hh" +#elif MSH_VARIANT == 23 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh23_nongradvec.hh" +#elif MSH_VARIANT == 24 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh24_nongradvec.hh" +#elif MSH_VARIANT == 25 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh25_nongradvec.hh" +#elif MSH_VARIANT == 26 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh26_nongradvec.hh" +#elif MSH_VARIANT == 27 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh27_nongradvec.hh" +#elif MSH_VARIANT == 28 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh28_nongradvec.hh" +#elif MSH_VARIANT == 29 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh29_nongradvec.hh" +#elif MSH_VARIANT == 30 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh30_nongradvec.hh" +#elif MSH_VARIANT == 31 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh31_nongradvec.hh" +#elif MSH_VARIANT == 32 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh32_nongradvec.hh" +#elif MSH_VARIANT == 33 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh33_nongradvec.hh" +#elif MSH_VARIANT == 34 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh34_nongradvec.hh" +#elif MSH_VARIANT == 35 && GRADVEC == 0 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh35_nongradvec.hh" +#elif MSH_VARIANT == 0 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh00_gradvec.hh" +#elif MSH_VARIANT == 1 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh01_gradvec.hh" +#elif MSH_VARIANT == 2 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh02_gradvec.hh" +#elif MSH_VARIANT == 3 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh03_gradvec.hh" +#elif MSH_VARIANT == 4 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh04_gradvec.hh" +#elif MSH_VARIANT == 5 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh05_gradvec.hh" +#elif MSH_VARIANT == 6 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh06_gradvec.hh" +#elif MSH_VARIANT == 7 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh07_gradvec.hh" +#elif MSH_VARIANT == 8 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh08_gradvec.hh" +#elif MSH_VARIANT == 9 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh09_gradvec.hh" +#elif MSH_VARIANT == 10 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh10_gradvec.hh" +#elif MSH_VARIANT == 11 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh11_gradvec.hh" +#elif MSH_VARIANT == 12 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh12_gradvec.hh" +#elif MSH_VARIANT == 13 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh13_gradvec.hh" +#elif MSH_VARIANT == 14 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh14_gradvec.hh" +#elif MSH_VARIANT == 15 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh15_gradvec.hh" +#elif MSH_VARIANT == 16 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh16_gradvec.hh" +#elif MSH_VARIANT == 17 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh17_gradvec.hh" +#elif MSH_VARIANT == 18 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh18_gradvec.hh" +#elif MSH_VARIANT == 19 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh19_gradvec.hh" +#elif MSH_VARIANT == 20 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh20_gradvec.hh" +#elif MSH_VARIANT == 21 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh21_gradvec.hh" +#elif MSH_VARIANT == 22 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh22_gradvec.hh" +#elif MSH_VARIANT == 23 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh23_gradvec.hh" +#elif MSH_VARIANT == 24 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh24_gradvec.hh" +#elif MSH_VARIANT == 25 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh25_gradvec.hh" +#elif MSH_VARIANT == 26 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh26_gradvec.hh" +#elif MSH_VARIANT == 27 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh27_gradvec.hh" +#elif MSH_VARIANT == 28 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh28_gradvec.hh" +#elif MSH_VARIANT == 29 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh29_gradvec.hh" +#elif MSH_VARIANT == 30 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh30_gradvec.hh" +#elif MSH_VARIANT == 31 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh31_gradvec.hh" +#elif MSH_VARIANT == 32 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh32_gradvec.hh" +#elif MSH_VARIANT == 33 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh33_gradvec.hh" +#elif MSH_VARIANT == 34 && GRADVEC == 1 +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh34_gradvec.hh" +#else +#include "sumfact_poisson_dg_3d_facedir_facemod_variation_localoperator_msh35_gradvec.hh" +#endif + +template <typename T> +bool isclose(T a, T b, double rel_tol=1e-9, double abs_tol=0.0){ + // Basically a python isclose (PEP 485) without error checking... + return std::abs(a-b) <= std::max(rel_tol*std::max(std::abs(a), std::abs(b)), abs_tol); +} + +template<typename T> +bool fuzzy_is_permutation(T a, T b, double rel_tol=1e-9, double abs_tol=1e-14){ + assert (a.size()==b.size()); + std::sort(a.begin(), a.end()); + std::sort(b.begin(), b.end()); + + for (std::size_t i=0; i<a.size(); ++i){ + if (!isclose(a[i], b[i], rel_tol, abs_tol)) + return false; + } + return true; +} + +template<typename GV> +void test_grid(GV gv){ + // iterate over all entities of the grid + for (const auto& e : elements(gv)) + { + std::cout << "## New Element!" << std::endl; + auto geo = e.geometry(); + for (int i=0; i<geo.corners(); i++){ + auto global_corner = geo.corner(i); + auto local_corner = geo.local(global_corner); + std::cout << "global_corner: "; + for (int i=0; i<3; ++i) + std::cout << global_corner[i] << " "; + std::cout << std::endl; + } + for (int i=0; i<geo.corners(); i++){ + auto global_corner = geo.corner(i); + auto local_corner = geo.local(global_corner); + std::cout << "local_corner: "; + for (int i=0; i<3; ++i) + std::cout << local_corner[i] << " "; + std::cout << std::endl; + } + } +} + + +int main(int argc, char** argv){ + try + { + std::cout << "Build test for MSH_VARIANT: " << MSH_VARIANT << std::endl; + + // Initialize basic stuff... + Dune::MPIHelper& mpihelper = Dune::MPIHelper::instance(argc, argv); + using RangeType = double; + Dune::ParameterTree initree; + Dune::ParameterTreeParser::readINITree(argv[1], initree); + + // Setup grid (view)... + using Grid = Dune::UGGrid<3>; + using GV = Grid::LeafGridView; + using DF = Grid::ctype; + IniGridFactory<Grid> factory(initree); + std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); + std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); + GV gv = grid->leafGridView(); + + // test_grid(gv); + + // Set up finite element maps... + using DG1_FEM = Dune::PDELab::QkDGLocalFiniteElementMap<DF, RangeType, 1, 3>; + DG1_FEM dg1_fem; + + // Set up grid function spaces... + using VectorBackendDG1 = Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::none>; + using NoConstraintsAssembler = Dune::PDELab::NoConstraints; + using DG1_GFS = Dune::PDELab::GridFunctionSpace<GV, DG1_FEM, NoConstraintsAssembler, VectorBackendDG1>; + DG1_GFS dg1_gfs_(gv, dg1_fem); + dg1_gfs_.name("dg1_gfs_"); + + // Set up constraints container... + using DG1_GFS_CC = DG1_GFS::ConstraintsContainer<RangeType>::Type; + DG1_GFS_CC dg1_gfs__cc; + dg1_gfs__cc.clear(); + Dune::PDELab::constraints(dg1_gfs_, dg1_gfs__cc); + + // Set up grid grid operators... + using LOP_R = CLASSNAME<DG1_GFS, DG1_GFS, RangeType>; + using MatrixBackend = Dune::PDELab::ISTL::BCRSMatrixBackend<>; + using GO_r = Dune::PDELab::GridOperator<DG1_GFS, DG1_GFS, LOP_R, MatrixBackend, DF, RangeType, RangeType, DG1_GFS_CC, DG1_GFS_CC>; + LOP_R lop_r(dg1_gfs_, dg1_gfs_, initree); + dg1_gfs_.update(); + int generic_dof_estimate = 8 * dg1_gfs_.maxLocalSize(); + int dofestimate = initree.get<int>("istl.number_of_nnz", generic_dof_estimate); + MatrixBackend mb(dofestimate); + GO_r go_r(dg1_gfs_, dg1_gfs__cc, dg1_gfs_, dg1_gfs__cc, lop_r, mb); + std::cout << "gfs with " << dg1_gfs_.size() << " dofs generated "<< std::endl; + std::cout << "cc with " << dg1_gfs__cc.size() << " dofs generated "<< std::endl; + + // Set up solution vectors... + using V_R = Dune::PDELab::Backend::Vector<DG1_GFS,DF>; + V_R x_r(dg1_gfs_); + x_r = 0.0; + auto lambda_0000 = [&](const auto& is, const auto& xl){ auto x=is.geometry().global(xl); return exp((-1.0) * ((0.5 - x[2]) * (0.5 - x[2]) + (0.5 - x[1]) * (0.5 - x[1]) + (0.5 - x[0]) * (0.5 - x[0])));; }; + auto func_0000 = Dune::PDELab::makeGridFunctionFromCallable(gv, lambda_0000); + + // Set up (non)linear solvers... + using LinearSolver = Dune::PDELab::ISTLBackend_SEQ_SuperLU; + using SLP = Dune::PDELab::StationaryLinearProblemSolver<GO_r, LinearSolver, V_R>; + LinearSolver ls(false); + double reduction = initree.get<double>("reduction", 1e-12); + SLP slp(go_r, ls, x_r, reduction); + // slp.apply(); + + // Do visualization... + using VTKWriter = Dune::SubsamplingVTKWriter<GV>; + Dune::RefinementIntervals subint(initree.get<int>("vtk.subsamplinglevel", 1)); + VTKWriter vtkwriter(gv, subint); + std::string vtkfile = initree.get<std::string>("wrapper.vtkcompare.name", "output"); + CuttingPredicate predicate; + Dune::PDELab::addSolutionToVTKWriter(vtkwriter, dg1_gfs_, x_r, Dune::PDELab::vtk::defaultNameScheme(), predicate); + vtkwriter.write(vtkfile, Dune::VTK::ascii); + + // Maybe print residuals and matrices to stdout... + if (initree.get<bool>("printresidual", false)) { + using Dune::PDELab::Backend::native; + V_R x_s(x_r); + // Interpolate input + auto interpolate_lambda = + [] (const auto& e, const auto& xl){ + auto xg = e.geometry().global(xl); + auto center = e.geometry().center(); + if (center.two_norm() < 2){ + return std::sin((xg.two_norm2()+xg[0]/3)/10); + } + else{ + return std::sin((xg.two_norm2())/10); + } + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_s); + Dune::printvector(std::cout, native(x_s), "x_s", "row"); + + V_R r(x_r); + r=0.0; + go_r.residual(x_s, r); + Dune::printvector(std::cout, native(r), "residual vector", "row"); + + + // std::cout.precision(17); + std::vector<RangeType> residual(16); + for (std::size_t i=0; i<16; ++i){ + residual[i] = native(r)[i]; + } + std::cout << "residual:" << std::endl; + for (std::size_t i=0; i<16; ++i){ + std::cout << residual[i] << ", "; + } + std::cout << std::endl; + + // One 'correct' numerical solution for unstructured grid + std::vector<RangeType> solution {-0.057104007824202004, -0.0024731701973568316, -0.046356852559280147, -0.0027796990290359386, -0.059846762373056507, -0.0018692117846729277, -0.059392343130923175, -0.001819348168293539, 0.0045404278062097974, 0.058001699047809038, 0.003253630695976081, 0.053457041807397923, 0.0029356233595935395, 0.055070262236853566, 0.0022382207545877291, 0.052144489358393387}; + + std::cout << "is_permuation: " + << fuzzy_is_permutation(solution, residual) << std::endl; + if (!fuzzy_is_permutation(solution, residual)){ + return 1; + } + } + if (initree.get<bool>("printmatrix", false)) { + using Dune::PDELab::Backend::native; + V_R r(x_r); + // Interpolate input + auto interpolate_lambda = [] (const auto& x){ + return std::exp(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]); + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_r); + using M = typename GO_r::Traits::Jacobian; + M m(go_r); + go_r.jacobian(x_r,m); + using Dune::PDELab::Backend::native; + Dune::printmatrix(std::cout, native(m),"global stiffness matrix","row",9,1); + } + + // // Maybe calculate errors for test results... + // using DG1_GFS__DGF = Dune::PDELab::DiscreteGridFunction<decltype(dg1_gfs_),decltype(x_r)>; + // DG1_GFS__DGF dg1_gfs__dgf(dg1_gfs_,x_r); + // using DifferenceSquaredAdapter_ = Dune::PDELab::DifferenceSquaredAdapter<decltype(func_0000), decltype(dg1_gfs__dgf)>; + // DifferenceSquaredAdapter_ dsa_(func_0000, dg1_gfs__dgf); + // Dune::FieldVector<RangeType, 1> l2error(0.0); + // { + // // L2 error squared of difference between numerical + // // solution and the interpolation of exact solution + // // for treepath () + // typename decltype(dsa_)::Traits::RangeType err(0.0); + // Dune::PDELab::integrateGridFunction(dsa_, err, 10); + + // l2error += err; + // if (gv.comm().rank() == 0){ + // std::cout << "L2 Error for treepath : " << err << std::endl; + // }} + // bool testfail(false); + // using std::abs; + // using std::isnan; + // if (gv.comm().rank() == 0){ + // std::cout << "\nl2errorsquared: " << l2error << std::endl << std::endl; + // } + // if (isnan(l2error[0]) or abs(l2error[0])>1e-4) + // testfail = true; + // return testfail; + return 0; + + } + catch (Dune::Exception& e) + { std::cerr << "Dune reported error: " << e << std::endl; + return 1; + } + catch (std::exception& e) + { std::cerr << "Unknown exception thrown!" << std::endl; + return 1; + } +} diff --git a/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation.mini b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation.mini new file mode 100644 index 0000000000000000000000000000000000000000..f814a9aac356cf416a358ff08816d346138d3d9a --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation.mini @@ -0,0 +1,50 @@ +__name = sumfact_poisson_fastdg_3d_facedir_facemod_variation_{__exec_suffix} +__exec_suffix = {deg_suffix}_{diff_suffix}_{quadvec_suffix}_{gradvec_suffix}_{msh_suffix} + +diff_suffix = numdiff, symdiff | expand num +quadvec_suffix = quadvec, nonquadvec | expand quad +gradvec_suffix = gradvec, nongradvec | expand grad +deg_suffix = deg{formcompiler.ufl_variants.degree} +msh_suffix = msh{msh_number} + + +# Be careful when you adjust these as the driver is handwritten! +{deg_suffix} == deg2 | exclude +{diff_suffix} == numdiff | exclude +{quadvec_suffix} == quadvec | exclude +# {gradvec_suffix} == gradvec | exclude + + +msh_number = 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 | expand +gmshFile = grid_unstructured_{msh_number}.msh +# gmshFile = grid_affine_{msh_number}.msh + +printresidual = 1 + + +[__static] +CLASSNAME = localoperator_fastdg_{msh_suffix}_{gradvec_suffix} +MSH_VARIANT = {msh_number} | toint +GRADVEC = 1, 0 | expand grad + +[wrapper.vtkcompare] +name = {__name} +extension = vtu + +[formcompiler] +compare_l2errorsquared = 1e-4, 5e-6 | expand deg +grid_unstructured = 1 +debug_interpolate_input = 1 + +[formcompiler.r] +classname = {__static.CLASSNAME} +filename = sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_{msh_suffix}_{gradvec_suffix}.hh +numerical_jacobian = 1, 0 | expand num +sumfact = 1 +sumfact_regular_jacobians = 1 +vectorization_quadloop = 1, 0 | expand quad +vectorization_strategy = model, none | expand grad +fastdg = 1 + +[formcompiler.ufl_variants] +degree = 1, 2 | expand deg diff --git a/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation_driver.cc b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation_driver.cc new file mode 100644 index 0000000000000000000000000000000000000000..90a5c381b538f8c41403161f96ba78a960fe491b --- /dev/null +++ b/test/sumfact/poisson/facedir-facemod-variation/sumfact_poisson_fastdg_3d_facedir_facemod_variation_driver.cc @@ -0,0 +1,371 @@ +#include "config.h" +#include "dune/common/parallel/mpihelper.hh" +#include "dune/pdelab/stationary/linearproblem.hh" +#include "dune/pdelab/backend/istl.hh" +#include "dune/pdelab/finiteelement/qkdglagrange.hh" +#include "dune/grid/uggrid.hh" +#include "dune/grid/yaspgrid.hh" +#include "dune/pdelab/finiteelementmap/qkdg.hh" +#include "dune/pdelab/gridoperator/fastdg.hh" +#include "dune/testtools/gridconstruction.hh" +#include "dune/common/parametertree.hh" +#include "dune/common/parametertreeparser.hh" +#include "dune/consistent-edge-orientation/createconsistentgrid.hh" +#include <random> +#include "dune/pdelab/gridfunctionspace/vtk.hh" +#include "dune/grid/io/file/vtk/subsamplingvtkwriter.hh" +#include "string" +#include "dune/codegen/vtkpredicate.hh" +#include "dune/pdelab/function/callableadapter.hh" +#include "dune/pdelab/gridfunctionspace/gridfunctionadapter.hh" +#include "dune/pdelab/common/functionutilities.hh" + +#if MSH_VARIANT == 0 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh00_nongradvec.hh" +#elif MSH_VARIANT == 1 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh01_nongradvec.hh" +#elif MSH_VARIANT == 2 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh02_nongradvec.hh" +#elif MSH_VARIANT == 3 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh03_nongradvec.hh" +#elif MSH_VARIANT == 4 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh04_nongradvec.hh" +#elif MSH_VARIANT == 5 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh05_nongradvec.hh" +#elif MSH_VARIANT == 6 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh06_nongradvec.hh" +#elif MSH_VARIANT == 7 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh07_nongradvec.hh" +#elif MSH_VARIANT == 8 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh08_nongradvec.hh" +#elif MSH_VARIANT == 9 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh09_nongradvec.hh" +#elif MSH_VARIANT == 10 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh10_nongradvec.hh" +#elif MSH_VARIANT == 11 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh11_nongradvec.hh" +#elif MSH_VARIANT == 12 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh12_nongradvec.hh" +#elif MSH_VARIANT == 13 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh13_nongradvec.hh" +#elif MSH_VARIANT == 14 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh14_nongradvec.hh" +#elif MSH_VARIANT == 15 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh15_nongradvec.hh" +#elif MSH_VARIANT == 16 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh16_nongradvec.hh" +#elif MSH_VARIANT == 17 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh17_nongradvec.hh" +#elif MSH_VARIANT == 18 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh18_nongradvec.hh" +#elif MSH_VARIANT == 19 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh19_nongradvec.hh" +#elif MSH_VARIANT == 20 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh20_nongradvec.hh" +#elif MSH_VARIANT == 21 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh21_nongradvec.hh" +#elif MSH_VARIANT == 22 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh22_nongradvec.hh" +#elif MSH_VARIANT == 23 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh23_nongradvec.hh" +#elif MSH_VARIANT == 24 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh24_nongradvec.hh" +#elif MSH_VARIANT == 25 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh25_nongradvec.hh" +#elif MSH_VARIANT == 26 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh26_nongradvec.hh" +#elif MSH_VARIANT == 27 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh27_nongradvec.hh" +#elif MSH_VARIANT == 28 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh28_nongradvec.hh" +#elif MSH_VARIANT == 29 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh29_nongradvec.hh" +#elif MSH_VARIANT == 30 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh30_nongradvec.hh" +#elif MSH_VARIANT == 31 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh31_nongradvec.hh" +#elif MSH_VARIANT == 32 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh32_nongradvec.hh" +#elif MSH_VARIANT == 33 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh33_nongradvec.hh" +#elif MSH_VARIANT == 34 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh34_nongradvec.hh" +#elif MSH_VARIANT == 35 && GRADVEC == 0 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh35_nongradvec.hh" +#elif MSH_VARIANT == 0 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh00_gradvec.hh" +#elif MSH_VARIANT == 1 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh01_gradvec.hh" +#elif MSH_VARIANT == 2 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh02_gradvec.hh" +#elif MSH_VARIANT == 3 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh03_gradvec.hh" +#elif MSH_VARIANT == 4 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh04_gradvec.hh" +#elif MSH_VARIANT == 5 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh05_gradvec.hh" +#elif MSH_VARIANT == 6 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh06_gradvec.hh" +#elif MSH_VARIANT == 7 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh07_gradvec.hh" +#elif MSH_VARIANT == 8 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh08_gradvec.hh" +#elif MSH_VARIANT == 9 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh09_gradvec.hh" +#elif MSH_VARIANT == 10 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh10_gradvec.hh" +#elif MSH_VARIANT == 11 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh11_gradvec.hh" +#elif MSH_VARIANT == 12 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh12_gradvec.hh" +#elif MSH_VARIANT == 13 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh13_gradvec.hh" +#elif MSH_VARIANT == 14 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh14_gradvec.hh" +#elif MSH_VARIANT == 15 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh15_gradvec.hh" +#elif MSH_VARIANT == 16 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh16_gradvec.hh" +#elif MSH_VARIANT == 17 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh17_gradvec.hh" +#elif MSH_VARIANT == 18 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh18_gradvec.hh" +#elif MSH_VARIANT == 19 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh19_gradvec.hh" +#elif MSH_VARIANT == 20 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh20_gradvec.hh" +#elif MSH_VARIANT == 21 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh21_gradvec.hh" +#elif MSH_VARIANT == 22 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh22_gradvec.hh" +#elif MSH_VARIANT == 23 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh23_gradvec.hh" +#elif MSH_VARIANT == 24 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh24_gradvec.hh" +#elif MSH_VARIANT == 25 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh25_gradvec.hh" +#elif MSH_VARIANT == 26 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh26_gradvec.hh" +#elif MSH_VARIANT == 27 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh27_gradvec.hh" +#elif MSH_VARIANT == 28 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh28_gradvec.hh" +#elif MSH_VARIANT == 29 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh29_gradvec.hh" +#elif MSH_VARIANT == 30 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh30_gradvec.hh" +#elif MSH_VARIANT == 31 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh31_gradvec.hh" +#elif MSH_VARIANT == 32 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh32_gradvec.hh" +#elif MSH_VARIANT == 33 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh33_gradvec.hh" +#elif MSH_VARIANT == 34 && GRADVEC == 1 +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh34_gradvec.hh" +#else +#include "sumfact_poisson_fastdg_3d_facedir_facemod_variation_localoperator_msh35_gradvec.hh" +#endif + + +template <typename T> +bool isclose(T a, T b, double rel_tol=1e-9, double abs_tol=0.0){ + // Basically a python isclose (PEP 485) without error checking... + return std::abs(a-b) <= std::max(rel_tol*std::max(std::abs(a), std::abs(b)), abs_tol); +} + +template<typename T> +bool fuzzy_is_permutation(T a, T b, double rel_tol=1e-9, double abs_tol=1e-14){ + assert (a.size()==b.size()); + std::sort(a.begin(), a.end()); + std::sort(b.begin(), b.end()); + + for (std::size_t i=0; i<a.size(); ++i){ + if (!isclose(a[i], b[i], rel_tol, abs_tol)) + return false; + } + return true; +} + + +int main(int argc, char** argv){ + try + { + std::cout << "Build fastdg test for MSH_VARIANT: " << MSH_VARIANT << std::endl; + + // Initialize basic stuff... + Dune::MPIHelper& mpihelper = Dune::MPIHelper::instance(argc, argv); + using RangeType = double; + Dune::ParameterTree initree; + Dune::ParameterTreeParser::readINITree(argv[1], initree); + + // Setup grid (view)... + using Grid = Dune::UGGrid<3>; + using GV = Grid::LeafGridView; + using DF = Grid::ctype; + IniGridFactory<Grid> factory(initree); + std::shared_ptr<Grid> grid_nonconsistent = factory.getGrid(); + std::shared_ptr<Grid> grid = createConsistentGrid(grid_nonconsistent); + GV gv = grid->leafGridView(); + + // Set up finite element maps... + using DG1_FEM = Dune::PDELab::QkDGLocalFiniteElementMap<DF, RangeType, 1, 3>; + DG1_FEM dg1_fem; + + // Set up grid function spaces... + using VectorBackendDG1 = Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::fixed, Dune::QkStuff::QkSize<1, 3>::value>; + using NoConstraintsAssembler = Dune::PDELab::NoConstraints; + using DG1_GFS = Dune::PDELab::GridFunctionSpace<GV, DG1_FEM, NoConstraintsAssembler, VectorBackendDG1>; + DG1_GFS dg1_gfs_(gv, dg1_fem); + dg1_gfs_.name("dg1_gfs_"); + + // Set up constraints container... + using DG1_GFS_CC = DG1_GFS::ConstraintsContainer<RangeType>::Type; + DG1_GFS_CC dg1_gfs__cc; + dg1_gfs__cc.clear(); + Dune::PDELab::constraints(dg1_gfs_, dg1_gfs__cc); + + // Set up grid grid operators... + using LOP_R = CLASSNAME<DG1_GFS, DG1_GFS, RangeType>; + using MatrixBackend = Dune::PDELab::ISTL::BCRSMatrixBackend<>; + using GO_r = Dune::PDELab::FastDGGridOperator<DG1_GFS, DG1_GFS, LOP_R, MatrixBackend, DF, RangeType, RangeType, DG1_GFS_CC, DG1_GFS_CC>; + LOP_R lop_r(dg1_gfs_, dg1_gfs_, initree); + dg1_gfs_.update(); + int generic_dof_estimate = 8 * dg1_gfs_.maxLocalSize(); + int dofestimate = initree.get<int>("istl.number_of_nnz", generic_dof_estimate); + MatrixBackend mb(dofestimate); + GO_r go_r(dg1_gfs_, dg1_gfs__cc, dg1_gfs_, dg1_gfs__cc, lop_r, mb); + std::cout << "gfs with " << dg1_gfs_.size() << " dofs generated "<< std::endl; + std::cout << "cc with " << dg1_gfs__cc.size() << " dofs generated "<< std::endl; + + // Set up solution vectors... + using V_R = Dune::PDELab::Backend::Vector<DG1_GFS,DF>; + V_R x_r(dg1_gfs_); + x_r = 0.0; + auto lambda_0000 = [&](const auto& is, const auto& xl){ auto x=is.geometry().global(xl); return exp((-1.0) * ((0.5 - x[2]) * (0.5 - x[2]) + (0.5 - x[1]) * (0.5 - x[1]) + (0.5 - x[0]) * (0.5 - x[0])));; }; + auto func_0000 = Dune::PDELab::makeGridFunctionFromCallable(gv, lambda_0000); + + // Set up (non)linear solvers... + using LinearSolver = Dune::PDELab::ISTLBackend_SEQ_SuperLU; + using SLP = Dune::PDELab::StationaryLinearProblemSolver<GO_r, LinearSolver, V_R>; + LinearSolver ls(false); + double reduction = initree.get<double>("reduction", 1e-12); + SLP slp(go_r, ls, x_r, reduction); + // slp.apply(); + + // Do visualization... + using VTKWriter = Dune::SubsamplingVTKWriter<GV>; + Dune::RefinementIntervals subint(initree.get<int>("vtk.subsamplinglevel", 1)); + VTKWriter vtkwriter(gv, subint); + std::string vtkfile = initree.get<std::string>("wrapper.vtkcompare.name", "output"); + CuttingPredicate predicate; + Dune::PDELab::addSolutionToVTKWriter(vtkwriter, dg1_gfs_, x_r, Dune::PDELab::vtk::defaultNameScheme(), predicate); + vtkwriter.write(vtkfile, Dune::VTK::ascii); + + // Maybe print residuals and matrices to stdout... + if (initree.get<bool>("printresidual", false)) { + using Dune::PDELab::Backend::native; + V_R x_s(x_r); + auto interpolate_lambda = + [] (const auto& e, const auto& xl){ + auto xg = e.geometry().global(xl); + auto center = e.geometry().center(); + if (center.two_norm() < 2){ + return std::sin((xg.two_norm2()+xg[0]/3)/10); + } + else{ + return std::sin((xg.two_norm2())/10); + } + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_s); + + V_R r(x_r); + r=0.0; + go_r.residual(x_s, r); + Dune::printvector(std::cout, native(r), "residual vector", "row"); + + + + + // native(r).blubber(); + // std::cout.precision(17); + std::vector<RangeType> residual(16); + std::size_t i = 0; + for (auto v : r){ + residual[i] = v; + i++; + } + // for (std::size_t i=0; i<16; ++i){ + // residual[i] = r[i]; + // } + std::cout << "residual:" << std::endl; + for (std::size_t i=0; i<16; ++i){ + std::cout << residual[i] << ", "; + } + std::cout << std::endl; + + // One 'correct' numerical solution for unstructured grid + std::vector<RangeType> solution {-0.057104007824202004, -0.0024731701973568316, -0.046356852559280147, -0.0027796990290359386, -0.059846762373056507, -0.0018692117846729277, -0.059392343130923175, -0.001819348168293539, 0.0045404278062097974, 0.058001699047809038, 0.003253630695976081, 0.053457041807397923, 0.0029356233595935395, 0.055070262236853566, 0.0022382207545877291, 0.052144489358393387}; + + std::cout << "is_permuation: " + << fuzzy_is_permutation(solution, residual) << std::endl; + if (!fuzzy_is_permutation(solution, residual)){ + return 1; + } + + + } + if (initree.get<bool>("printmatrix", false)) { + using Dune::PDELab::Backend::native; + V_R r(x_r); + // Interpolate input + auto interpolate_lambda = [] (const auto& x){ + return std::exp(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]); + }; + auto interpolate = Dune::PDELab::makeGridFunctionFromCallable(gv, interpolate_lambda); + Dune::PDELab::interpolate(interpolate,dg1_gfs_,x_r); + using M = typename GO_r::Traits::Jacobian; + M m(go_r); + go_r.jacobian(x_r,m); + using Dune::PDELab::Backend::native; + Dune::printmatrix(std::cout, native(m),"global stiffness matrix","row",9,1); + } + + // // Maybe calculate errors for test results... + // using DG1_GFS__DGF = Dune::PDELab::DiscreteGridFunction<decltype(dg1_gfs_),decltype(x_r)>; + // DG1_GFS__DGF dg1_gfs__dgf(dg1_gfs_,x_r); + // using DifferenceSquaredAdapter_ = Dune::PDELab::DifferenceSquaredAdapter<decltype(func_0000), decltype(dg1_gfs__dgf)>; + // DifferenceSquaredAdapter_ dsa_(func_0000, dg1_gfs__dgf); + // Dune::FieldVector<RangeType, 1> l2error(0.0); + // { + // // L2 error squared of difference between numerical + // // solution and the interpolation of exact solution + // // for treepath () + // typename decltype(dsa_)::Traits::RangeType err(0.0); + // Dune::PDELab::integrateGridFunction(dsa_, err, 10); + + // l2error += err; + // if (gv.comm().rank() == 0){ + // std::cout << "L2 Error for treepath : " << err << std::endl; + // }} + // bool testfail(false); + // using std::abs; + // using std::isnan; + // if (gv.comm().rank() == 0){ + // std::cout << "\nl2errorsquared: " << l2error << std::endl << std::endl; + // } + // if (isnan(l2error[0]) or abs(l2error[0])>1e-4) + // testfail = true; + // return testfail; + return 0; + + } + catch (Dune::Exception& e) + { std::cerr << "Dune reported error: " << e << std::endl; + return 1; + } + catch (std::exception& e) + { std::cerr << "Unknown exception thrown!" << std::endl; + return 1; + } +} diff --git a/test/sumfact/poisson/poisson_2d_unstructured.mini b/test/sumfact/poisson/poisson_2d_unstructured.mini index 5eabe782259e3fd7396f59e63f3f131a0bf800e1..ce12ec78f77d940a8b8cec3081a5a9708ece0f56 100644 --- a/test/sumfact/poisson/poisson_2d_unstructured.mini +++ b/test/sumfact/poisson/poisson_2d_unstructured.mini @@ -13,7 +13,7 @@ deg_suffix = deg{formcompiler.ufl_variants.degree} lowerleft = 0.0 0.0 upperright = 1.0 1.0 -elements = 16 16 +elements = 8 8 elementType = quadrilateral [wrapper.vtkcompare] @@ -29,7 +29,7 @@ debug_interpolate_input = 1 numerical_jacobian = 1, 0 | expand num sumfact = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_3d_unstructured.mini b/test/sumfact/poisson/poisson_3d_unstructured.mini index 0cbf2814f2802f0cc60e1964eb1471ca337cdab3..7d5710fa68d588a96d4ed23aac0ea72dff6276c6 100644 --- a/test/sumfact/poisson/poisson_3d_unstructured.mini +++ b/test/sumfact/poisson/poisson_3d_unstructured.mini @@ -29,7 +29,7 @@ debug_interpolate_input = 1 numerical_jacobian = 1, 0 | expand num sumfact = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_dg_2d_gmsh.mini b/test/sumfact/poisson/poisson_dg_2d_gmsh.mini index 054a2481cef270cdb3b290f1a85ff6d7b5f991a0..8d622b06ff3e6a83b140a6c6db00929fd8fb8c86 100644 --- a/test/sumfact/poisson/poisson_dg_2d_gmsh.mini +++ b/test/sumfact/poisson/poisson_dg_2d_gmsh.mini @@ -11,8 +11,7 @@ deg_suffix = deg{formcompiler.ufl_variants.degree} {quadvec_suffix} == quadvec | exclude {gradvec_suffix} == gradvec | exclude -# gmshFile = square_quad.msh -gmshFile = square_quad_consistent.msh +gmshFile = square_quad.msh [wrapper.vtkcompare] name = {__name} @@ -28,7 +27,7 @@ numerical_jacobian = 1, 0 | expand num sumfact = 1 sumfact_regular_jacobians = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_dg_2d_unstructured.mini b/test/sumfact/poisson/poisson_dg_2d_unstructured.mini index 55336ae70bd6a852999ba7b549fa34026ffa8f72..eca089ff89316487fda300c4b45947b5b2d0b83b 100644 --- a/test/sumfact/poisson/poisson_dg_2d_unstructured.mini +++ b/test/sumfact/poisson/poisson_dg_2d_unstructured.mini @@ -9,7 +9,6 @@ deg_suffix = deg{formcompiler.ufl_variants.degree} {deg_suffix} == deg1 | exclude {diff_suffix} == numdiff | exclude {quadvec_suffix} == quadvec | exclude -{gradvec_suffix} == gradvec | exclude lowerleft = 0.0 0.0 upperright = 1.0 1.0 @@ -29,7 +28,7 @@ debug_interpolate_input = 1 numerical_jacobian = 1, 0 | expand num sumfact = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_dg_3d.mini b/test/sumfact/poisson/poisson_dg_3d.mini index db9dc2e3c2f719c17d0b619abc946664103fe8b5..3f0485672102ab0d7fffd7ce4f490c0f86a66cff 100644 --- a/test/sumfact/poisson/poisson_dg_3d.mini +++ b/test/sumfact/poisson/poisson_dg_3d.mini @@ -15,6 +15,7 @@ extension = vtu [formcompiler] compare_l2errorsquared = 1e-4, 5e-6 | expand deg +debug_interpolate_input = 1 [formcompiler.r] numerical_jacobian = 1, 0 | expand num diff --git a/test/sumfact/poisson/poisson_dg_3d_gmsh.mini b/test/sumfact/poisson/poisson_dg_3d_gmsh.mini index 0216093fd541ba7dabec2c9bb3b501833faa2924..fb9b26801ac504ecac69f58d4c0a1f305ce16ccd 100644 --- a/test/sumfact/poisson/poisson_dg_3d_gmsh.mini +++ b/test/sumfact/poisson/poisson_dg_3d_gmsh.mini @@ -12,9 +12,7 @@ deg_suffix = deg{formcompiler.ufl_variants.degree} {gradvec_suffix} == gradvec | exclude # gmshFile = cube_hexa_2.msh -# gmshFile = cube_hexa_2_consistent.msh -# gmshFile = cube_hexa.msh -gmshFile = cube_hexa_consistent.msh +gmshFile = cube_hexa.msh [wrapper.vtkcompare] name = {__name} @@ -30,7 +28,7 @@ numerical_jacobian = 1, 0 | expand num sumfact = 1 sumfact_regular_jacobians = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_dg_3d_unstructured.mini b/test/sumfact/poisson/poisson_dg_3d_unstructured.mini index c42be3b948c0513f6aed7f3c4a00d9e546f22bb1..ed80ba617c1d91b66d1df9e7b5ecfc508d71fc77 100644 --- a/test/sumfact/poisson/poisson_dg_3d_unstructured.mini +++ b/test/sumfact/poisson/poisson_dg_3d_unstructured.mini @@ -6,10 +6,9 @@ quadvec_suffix = quadvec, nonquadvec | expand quad gradvec_suffix = gradvec, nongradvec | expand grad deg_suffix = deg{formcompiler.ufl_variants.degree} -# {deg_suffix} == deg1 | exclude +{deg_suffix} == deg1 | exclude {diff_suffix} == numdiff | exclude {quadvec_suffix} == quadvec | exclude -{gradvec_suffix} == gradvec | exclude lowerleft = 0.0 0.0 0.0 upperright = 1.0 1.0 1.0 @@ -30,7 +29,7 @@ numerical_jacobian = 1, 0 | expand num sumfact = 1 sumfact_regular_jacobians = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/poisson_fastdg_2d_gmsh.mini b/test/sumfact/poisson/poisson_fastdg_2d_gmsh.mini new file mode 100644 index 0000000000000000000000000000000000000000..56b69c773b1ce95fa6387f5313af47a94980f8c0 --- /dev/null +++ b/test/sumfact/poisson/poisson_fastdg_2d_gmsh.mini @@ -0,0 +1,32 @@ +__name = sumfact_poisson_fastdg_2d_gmsh_{__exec_suffix} +__exec_suffix = {deg_suffix}_{quadvec_suffix}_{gradvec_suffix} + +quadvec_suffix = quadvec, nonquadvec | expand quad +gradvec_suffix = gradvec, nongradvec | expand grad +deg_suffix = deg{formcompiler.ufl_variants.degree} + +# {deg_suffix} == deg1 | exclude +{quadvec_suffix} == quadvec | exclude +# {gradvec_suffix} == gradvec | exclude + +gmshFile = square_quad.msh + +[wrapper.vtkcompare] +name = {__name} +extension = vtu + +[formcompiler] +compare_l2errorsquared = 5e-5, 5e-7 | expand deg +grid_unstructured = 1 +debug_interpolate_input = 1 + +[formcompiler.r] +numerical_jacobian = 0 +sumfact = 1 +fastdg = 1 +sumfact_regular_jacobians = 1 +vectorization_quadloop = 1, 0 | expand quad +vectorization_strategy = model, none | expand grad + +[formcompiler.ufl_variants] +degree = 1, 2 | expand deg diff --git a/test/sumfact/poisson/poisson_fastdg_3d_gmsh.mini b/test/sumfact/poisson/poisson_fastdg_3d_gmsh.mini index a6374d18e2068f553d9577df7da1b6d51eb9922d..ada6f4aed8cc1769b4793d8f1c6f7ee55ba2cbb3 100644 --- a/test/sumfact/poisson/poisson_fastdg_3d_gmsh.mini +++ b/test/sumfact/poisson/poisson_fastdg_3d_gmsh.mini @@ -7,12 +7,8 @@ deg_suffix = deg{formcompiler.ufl_variants.degree} {deg_suffix} == deg1 | exclude {quadvec_suffix} == quadvec | exclude -{gradvec_suffix} == gradvec | exclude -# gmshFile = cube_hexa_2.msh -# gmshFile = cube_hexa_2_consistent.msh -# gmshFile = cube_hexa.msh -gmshFile = cube_hexa_consistent.msh +gmshFile = cube_hexa.msh [wrapper.vtkcompare] name = {__name} @@ -29,7 +25,7 @@ sumfact = 1 fastdg = 1 sumfact_regular_jacobians = 1 vectorization_quadloop = 1, 0 | expand quad -vectorization_strategy = explicit, none | expand grad +vectorization_strategy = model, none | expand grad geometry_mixins = sumfact_multilinear [formcompiler.ufl_variants] diff --git a/test/sumfact/poisson/square_quad_consistent.msh b/test/sumfact/poisson/square_quad_consistent.msh deleted file mode 100644 index 49986d0a012865d78c9dcbe86a7a1b8f42829771..0000000000000000000000000000000000000000 --- a/test/sumfact/poisson/square_quad_consistent.msh +++ /dev/null @@ -1,692 +0,0 @@ -$MeshFormat -2.0 0 8 -$EndMeshFormat -$Nodes -358 -1 0 0 0 -2 0.0625 0 0 -3 0.125 0 0 -4 0.1875 0 0 -5 0.25 0 0 -6 0.3125 0 0 -7 0.375 0 0 -8 0.4375 0 0 -9 0.5 0 0 -10 0.5625 0 0 -11 0.625 0 0 -12 0.6875 0 0 -13 0.75 0 0 -14 0.8125 0 0 -15 0.875 0 0 -16 0.9375 0 0 -17 1 0 0 -18 1 0.0625 0 -19 1 0.125 0 -20 1 0.1875 0 -21 1 0.25 0 -22 1 0.3125 0 -23 1 0.375 0 -24 1 0.4375 0 -25 1 0.5 0 -26 1 0.5625 0 -27 1 0.625 0 -28 1 0.6875 0 -29 1 0.75 0 -30 1 0.8125 0 -31 1 0.875 0 -32 1 0.9375 0 -33 1 1 0 -34 0.9375 1 0 -35 0.875 1 0 -36 0.8125 1 0 -37 0.75 1 0 -38 0.6875 1 0 -39 0.625 1 0 -40 0.5625 1 0 -41 0.5 1 0 -42 0.4375 1 0 -43 0.375 1 0 -44 0.3125 1 0 -45 0.25 1 0 -46 0.1875 1 0 -47 0.125 1 0 -48 0.0625 1 0 -49 0 1 0 -50 0 0.9375 0 -51 0 0.875 0 -52 0 0.8125 0 -53 0 0.75 0 -54 0 0.6875 0 -55 0 0.625 0 -56 0 0.5625 0 -57 0 0.5 0 -58 0 0.4375 0 -59 0 0.375 0 -60 0 0.3125 0 -61 0 0.25 0 -62 0 0.1875 0 -63 0 0.125 0 -64 0 0.0625 0 -65 0.399202 0.487152 0 -66 0.424295 0.542237 0 -67 0.37289 0.569861 0 -68 0.353221 0.50996 0 -69 0.3969 0.404475 0 -70 0.443052 0.442259 0 -71 0.380047 0.449702 0 -72 0.859834 0.63296 0 -73 0.846984 0.575746 0 -74 0.89676 0.56734 0 -75 0.911823 0.614461 0 -76 0.580477 0.0889589 0 -77 0.620359 0.0983843 0 -78 0.634059 0.136321 0 -79 0.563218 0.142236 0 -80 0.933128 0.14552 0 -81 0.943465 0.224682 0 -82 0.921357 0.193691 0 -83 0.537239 0.757926 0 -84 0.609646 0.751065 0 -85 0.595958 0.799189 0 -86 0.55671 0.809449 0 -87 0.243662 0.543734 0 -88 0.249949 0.615521 0 -89 0.201578 0.599437 0 -90 0.191785 0.559736 0 -91 0.763782 0.465445 0 -92 0.743379 0.397186 0 -93 0.796056 0.406379 0 -94 0.814516 0.445298 0 -95 0.472143 0.246812 0 -96 0.396912 0.269342 0 -97 0.407226 0.207102 0 -98 0.446499 0.193178 0 -99 0.773888 0.869189 0 -100 0.797571 0.924664 0 -101 0.746322 0.94513 0 -102 0.730478 0.894719 0 -103 0.130634 0.774459 0 -104 0.0753069 0.797663 0 -105 0.0548538 0.746415 0 -106 0.105245 0.73075 0 -107 0.881658 0.20409 0 -108 0.899061 0.254568 0 -109 0.225743 0.130943 0 -110 0.202374 0.0753367 0 -111 0.253647 0.0549043 0 -112 0.269451 0.105432 0 -113 0.757732 0.0548751 0 -114 0.813002 0.0534436 0 -115 0.815949 0.10677 0 -116 0.761722 0.111049 0 -117 0.385502 0.888477 0 -118 0.436638 0.83986 0 -119 0.471169 0.901026 0 -120 0.422797 0.933941 0 -121 0.111671 0.38565 0 -122 0.160997 0.437322 0 -123 0.0993231 0.471565 0 -124 0.0661749 0.422903 0 -125 0.284733 0.453522 0 -126 0.343849 0.454368 0 -127 0.299852 0.527081 0 -128 0.342196 0.402711 0 -129 0.338786 0.348311 0 -130 0.393166 0.352017 0 -131 0.949981 0.712411 0 -132 0.931761 0.662022 0 -133 0.287389 0.948805 0 -134 0.337878 0.925072 0 -135 0.0511875 0.287385 0 -136 0.0749266 0.337891 0 -137 0.955781 0.0695517 0 -138 0.0670949 0.0429529 0 -139 0.932904 0.957047 0 -140 0.0429534 0.932905 0 -141 0.502805 0.825707 0 -142 0.480396 0.77525 0 -143 0.175716 0.504858 0 -144 0.227986 0.484354 0 -145 0.845533 0.50779 0 -146 0.779027 0.524674 0 -147 0.501632 0.172353 0 -148 0.53063 0.224761 0 -149 0.447105 0.36522 0 -150 0.878467 0.685636 0 -151 0.695571 0.107169 0 -152 0.647029 0.0664687 0 -153 0.307376 0.874066 0 -154 0.347911 0.843851 0 -155 0.125884 0.307417 0 -156 0.156102 0.347967 0 -157 0.668541 0.719188 0 -158 0.70563 0.766064 0 -159 0.663064 0.798521 0 -160 0.283837 0.676102 0 -161 0.234155 0.710149 0 -162 0.201805 0.665721 0 -163 0.322874 0.292425 0 -164 0.291092 0.238326 0 -165 0.337328 0.206512 0 -166 0.601815 0.0456832 0 -167 0.655693 0.874729 0 -168 0.610971 0.902858 0 -169 0.579503 0.856871 0 -170 0.623893 0.830258 0 -171 0.125349 0.65658 0 -172 0.0972211 0.611431 0 -173 0.143588 0.580889 0 -174 0.169966 0.625744 0 -175 0.875404 0.340085 0 -176 0.909004 0.389919 0 -177 0.862842 0.420264 0 -178 0.826357 0.376066 0 -179 0.344526 0.126355 0 -180 0.38918 0.0975207 0 -181 0.421576 0.144223 0 -182 0.376978 0.17235 0 -183 0.724165 0.5374 0 -184 0.668304 0.54495 0 -185 0.662611 0.488844 0 -186 0.712439 0.481187 0 -187 0.892089 0.531009 0 -188 0.664629 0.437153 0 -189 0.704556 0.441311 0 -190 0.500865 0.375508 0 -191 0.450553 0.31738 0 -192 0.504377 0.309758 0 -193 0.451453 0.729306 0 -194 0.509376 0.69345 0 -195 0.560874 0.275834 0 -196 0.570571 0.644827 0 -197 0.583609 0.686151 0 -198 0.526574 0.632104 0 -199 0.522793 0.0605664 0 -200 0.445221 0.0616836 0 -201 0.0499253 0.49227 0 -202 0.0616803 0.554783 0 -203 0.49218 0.95015 0 -204 0.554783 0.93832 0 -205 0.470397 0.511809 0 -206 0.50414 0.43657 0 -207 0.512746 0.493808 0 -208 0.442355 0.789976 0 -209 0.21292 0.443798 0 -210 0.792977 0.586789 0 -211 0.592284 0.204861 0 -212 0.640863 0.669518 0 -213 0.693639 0.659005 0 -214 0.704565 0.699257 0 -215 0.337512 0.651009 0 -216 0.358694 0.717955 0 -217 0.303703 0.714895 0 -218 0.651051 0.336286 0 -219 0.637064 0.303696 0 -220 0.69073 0.294033 0 -221 0.693988 0.339688 0 -222 0.277942 0.359575 0 -223 0.283214 0.306358 0 -224 0.379331 0.80411 0 -225 0.196042 0.379594 0 -226 0.203125 0.937024 0 -227 0.13514 0.946804 0 -228 0.93701 0.796866 0 -229 0.946779 0.864857 0 -230 0.0629717 0.203115 0 -231 0.0531951 0.135136 0 -232 0.866108 0.0499012 0 -233 0.527026 0.878545 0 -234 0.121904 0.527698 0 -235 0.897043 0.467117 0 -236 0.9407 0.439214 0 -237 0.472951 0.122156 0 -238 0.768229 0.338251 0 -239 0.680798 0.386665 0 -240 0.500542 0.55803 0 -241 0.523425 0.530238 0 -242 0.747813 0.295075 0 -243 0.737414 0.597736 0 -244 0.805538 0.646994 0 -245 0.749209 0.65655 0 -246 0.617052 0.256903 0 -247 0.653341 0.188996 0 -248 0.674114 0.244318 0 -249 0.419295 0.682615 0 -250 0.459097 0.663104 0 -251 0.67927 0.602976 0 -252 0.588439 0.320768 0 -253 0.551283 0.336537 0 -254 0.699526 0.845833 0 -255 0.74369 0.816069 0 -256 0.154181 0.700613 0 -257 0.183658 0.745255 0 -258 0.83282 0.282727 0 -259 0.783728 0.26642 0 -260 0.300341 0.155444 0 -261 0.255285 0.184687 0 -262 0.823118 0.842661 0 -263 0.874507 0.819691 0 -264 0.896304 0.872913 0 -265 0.847204 0.896425 0 -266 0.157138 0.823465 0 -267 0.179898 0.87478 0 -268 0.127016 0.89639 0 -269 0.10353 0.847303 0 -270 0.821848 0.161436 0 -271 0.867333 0.100001 0 -272 0.873828 0.152277 0 -273 0.176581 0.157193 0 -274 0.125224 0.179938 0 -275 0.103616 0.127022 0 -276 0.152717 0.103544 0 -277 0.754045 0.723044 0 -278 0.822569 0.706754 0 -279 0.847218 0.763831 0 -280 0.792878 0.787585 0 -281 0.274181 0.762121 0 -282 0.284959 0.82535 0 -283 0.234523 0.847862 0 -284 0.211062 0.794958 0 -285 0.727826 0.233557 0 -286 0.713035 0.176651 0 -287 0.768832 0.168288 0 -288 0.778234 0.223951 0 -289 0.237393 0.275464 0 -290 0.174484 0.285069 0 -291 0.152092 0.234562 0 -292 0.205119 0.211608 0 -293 0.394162 0.628615 0 -294 0.316568 0.590824 0 -295 0.450128 0.962742 0 -296 0.0373284 0.450203 0 -297 0.928869 0.514998 0 -298 0.945971 0.562863 0 -299 0.564161 0.0338811 0 -300 0.461388 0.606575 0 -301 0.687135 0.92006 0 -302 0.708154 0.952757 0 -303 0.0799277 0.687368 0 -304 0.0472327 0.708249 0 -305 0.938613 0.305476 0 -306 0.962616 0.257549 0 -307 0.31287 0.0801107 0 -308 0.291836 0.0472977 0 -309 0.82976 0.215972 0 -310 0.645043 0.945272 0 -311 0.0547378 0.645223 0 -312 0.958071 0.359828 0 -313 0.354993 0.0548861 0 -314 0.900312 0.739664 0 -315 0.963539 0.751235 0 -316 0.2594 0.899685 0 -317 0.248733 0.963315 0 -318 0.100295 0.259378 0 -319 0.036681 0.248727 0 -320 0.872926 0.939511 0 -321 0.0604893 0.872926 0 -322 0.127074 0.0604891 0 -323 0.559655 0.48827 0 -324 0.55645 0.433945 0 -325 0.61212 0.433765 0 -326 0.609874 0.489333 0 -327 0.554692 0.377756 0 -328 0.611347 0.544304 0 -329 0.558195 0.538058 0 -330 0.608853 0.610338 0 -331 0.408859 0.761733 0 -332 0.239751 0.408729 0 -333 0.617685 0.370632 0 -334 0.715801 0.0560456 0 -335 0.89216 0.967674 0 -336 0.916639 0.916874 0 -337 0.0323265 0.892161 0 -338 0.0831266 0.916649 0 -339 0.965699 0.112627 0 -340 0.913305 0.086121 0 -341 0.107839 0.0323262 0 -342 0.0833512 0.0831243 0 -343 0.948908 0.599189 0 -344 0.332969 0.777157 0 -345 0.22214 0.33329 0 -346 0.545894 0.584127 0 -347 0.515912 0.108468 0 -348 0.321067 0.814664 0 -349 0.185099 0.321288 0 -350 0.304477 0.403561 0 -351 0.0365225 0.612334 0 -352 0.612255 0.963485 0 -353 0.967408 0.41527 0 -354 0.387766 0.0365794 0 -355 0.950864 0.904453 0 -356 0.903402 0.0489299 0 -357 0.0955472 0.950875 0 -358 0.0491254 0.095545 0 -$EndNodes -$Elements -325 -1 3 0 66 67 68 65 -2 3 0 70 65 71 69 -3 3 0 73 74 75 72 -4 3 0 77 78 79 76 -5 3 0 81 82 80 20 -6 3 0 84 85 86 83 -7 3 0 88 89 90 87 -8 3 0 91 92 93 94 -9 3 0 96 97 98 95 -10 3 0 100 101 102 99 -11 3 0 104 105 106 103 -12 3 0 81 108 107 82 -13 3 0 111 112 109 110 -14 3 0 113 114 115 116 -15 3 0 118 119 120 117 -16 3 0 122 123 124 121 -17 3 0 68 127 125 126 -18 3 0 69 128 129 130 -19 3 0 28 131 132 27 -20 3 0 133 134 43 44 -21 3 0 135 136 59 60 -22 3 0 17 18 137 16 -23 3 0 2 138 64 1 -24 3 0 139 32 33 34 -25 3 0 49 50 140 48 -26 3 0 83 86 141 142 -27 3 0 87 90 143 144 -28 3 0 146 91 94 145 -29 3 0 148 95 98 147 -30 3 0 70 69 130 149 -31 3 0 150 72 75 132 -32 3 0 77 152 151 78 -33 3 0 134 153 154 117 -34 3 0 136 155 156 121 -35 3 0 157 158 159 84 -36 3 0 160 161 162 88 -37 3 0 96 163 164 165 -38 3 0 12 152 166 11 -39 3 0 167 168 169 170 -40 3 0 171 172 173 174 -41 3 0 176 177 178 175 -42 3 0 179 180 181 182 -43 3 0 184 185 186 183 -44 3 0 73 145 187 74 -45 3 0 185 188 189 186 -46 3 0 191 192 190 149 -47 3 0 83 142 193 194 -48 3 0 87 144 125 127 -49 3 0 183 186 91 146 -50 3 0 195 192 95 148 -51 3 0 196 197 194 198 -52 3 0 9 199 200 8 -53 3 0 56 57 201 202 -54 3 0 40 41 203 204 -55 3 0 205 70 206 207 -56 3 0 142 141 118 208 -57 3 0 144 143 122 209 -58 3 0 210 146 145 73 -59 3 0 211 148 147 79 -60 3 0 214 157 212 213 -61 3 0 160 215 216 217 -62 3 0 220 221 218 219 -63 3 0 163 129 222 223 -64 3 0 70 149 190 206 -65 3 0 118 117 154 224 -66 3 0 122 121 156 225 -67 3 0 227 226 46 47 -68 3 0 31 229 228 30 -69 3 0 231 230 62 63 -70 3 0 14 15 232 114 -71 3 0 168 204 233 169 -72 3 0 172 202 234 173 -73 3 0 236 235 177 176 -74 3 0 200 237 181 180 -75 3 0 221 238 92 239 -76 3 0 240 205 207 241 -77 3 0 86 169 233 141 -78 3 0 90 173 234 143 -79 3 0 235 145 94 177 -80 3 0 147 98 181 237 -81 3 0 85 170 169 86 -82 3 0 89 174 173 90 -83 3 0 177 94 93 178 -84 3 0 97 182 181 98 -85 3 0 220 242 238 221 -86 3 0 243 210 244 245 -87 3 0 248 246 211 247 -88 3 0 100 36 37 101 -89 3 0 104 52 53 105 -90 3 0 111 110 4 5 -91 3 0 194 193 249 250 -92 3 0 251 184 183 243 -93 3 0 252 253 192 195 -94 3 0 84 159 170 85 -95 3 0 88 162 174 89 -96 3 0 238 178 93 92 -97 3 0 96 165 182 97 -98 3 0 255 254 159 158 -99 3 0 257 256 162 161 -100 3 0 259 258 238 242 -101 3 0 260 165 164 261 -102 3 0 265 262 263 264 -103 3 0 269 266 267 268 -104 3 0 270 115 271 272 -105 3 0 276 273 274 275 -106 3 0 280 277 278 279 -107 3 0 284 281 282 283 -108 3 0 288 285 286 287 -109 3 0 292 289 290 291 -110 3 0 293 215 294 67 -111 3 0 41 42 295 203 -112 3 0 57 58 296 201 -113 3 0 26 298 297 25 -114 3 0 9 10 299 199 -115 3 0 198 194 250 300 -116 3 0 240 300 66 205 -117 3 0 101 302 301 102 -118 3 0 105 304 303 106 -119 3 0 81 306 305 108 -120 3 0 111 308 307 112 -121 3 0 99 102 254 255 -122 3 0 103 106 256 257 -123 3 0 258 309 107 108 -124 3 0 112 260 261 109 -125 3 0 301 310 168 167 -126 3 0 303 311 172 171 -127 3 0 176 175 305 312 -128 3 0 307 313 180 179 -129 3 0 228 314 131 315 -130 3 0 317 226 316 133 -131 3 0 319 230 318 135 -132 3 0 236 25 297 235 -133 3 0 302 38 310 301 -134 3 0 304 54 311 303 -135 3 0 308 6 313 307 -136 3 0 265 320 36 100 -137 3 0 104 269 321 52 -138 3 0 110 276 322 4 -139 3 0 326 323 324 325 -140 3 0 185 326 325 188 -141 3 0 324 206 190 327 -142 3 0 253 327 190 192 -143 3 0 263 279 314 228 -144 3 0 226 267 283 316 -145 3 0 274 291 318 230 -146 3 0 102 301 167 254 -147 3 0 106 303 171 256 -148 3 0 258 108 305 175 -149 3 0 112 307 179 260 -150 3 0 317 45 46 226 -151 3 0 30 228 315 29 -152 3 0 319 61 62 230 -153 3 0 13 14 114 113 -154 3 0 328 329 323 326 -155 3 0 205 66 65 70 -156 3 0 330 212 197 196 -157 3 0 300 293 67 66 -158 3 0 323 207 206 324 -159 3 0 251 330 328 184 -160 3 0 312 305 22 23 -161 3 0 142 208 331 193 -162 3 0 243 183 146 210 -163 3 0 144 209 332 125 -164 3 0 246 195 148 211 -165 3 0 252 333 327 253 -166 3 0 12 334 151 152 -167 3 0 335 320 336 139 -168 3 0 321 338 140 337 -169 3 0 339 80 340 137 -170 3 0 322 342 138 341 -171 3 0 42 43 120 295 -172 3 0 58 59 124 296 -173 3 0 26 27 343 298 -174 3 0 11 166 299 10 -175 3 0 317 133 44 45 -176 3 0 29 315 131 28 -177 3 0 319 135 60 61 -178 3 0 13 113 334 12 -179 3 0 84 83 194 197 -180 3 0 88 87 127 294 -181 3 0 186 189 92 91 -182 3 0 191 96 95 192 -183 3 0 331 224 344 216 -184 3 0 222 332 225 345 -185 3 0 251 213 212 330 -186 3 0 293 249 216 215 -187 3 0 219 218 333 252 -188 3 0 346 198 300 240 -189 3 0 330 196 198 346 -190 3 0 306 21 22 305 -191 3 0 27 132 75 343 -192 3 0 77 76 166 152 -193 3 0 134 117 120 43 -194 3 0 136 121 124 59 -195 3 0 204 203 119 233 -196 3 0 202 201 123 234 -197 3 0 199 347 237 200 -198 3 0 214 213 245 277 -199 3 0 217 216 344 281 -200 3 0 220 219 246 248 -201 3 0 223 222 345 289 -202 3 0 203 295 120 119 -203 3 0 201 296 124 123 -204 3 0 298 74 187 297 -205 3 0 76 79 347 199 -206 3 0 210 73 72 244 -207 3 0 247 211 79 78 -208 3 0 224 154 348 344 -209 3 0 345 225 156 349 -210 3 0 314 150 132 131 -211 3 0 113 116 151 334 -212 3 0 133 316 153 134 -213 3 0 135 318 155 136 -214 3 0 259 288 309 258 -215 3 0 288 287 270 309 -216 3 0 330 346 329 328 -217 3 0 157 84 197 212 -218 3 0 160 88 294 215 -219 3 0 221 239 333 218 -220 3 0 96 130 129 163 -221 3 0 141 233 119 118 -222 3 0 143 234 123 122 -223 3 0 235 297 187 145 -224 3 0 79 147 237 347 -225 3 0 277 245 244 278 -226 3 0 281 344 348 282 -227 3 0 248 247 286 285 -228 3 0 289 345 349 290 -229 3 0 193 331 216 249 -230 3 0 251 243 245 213 -231 3 0 350 125 332 222 -232 3 0 219 252 195 246 -233 3 0 262 280 279 263 -234 3 0 266 284 283 267 -235 3 0 287 116 115 270 -236 3 0 273 292 291 274 -237 3 0 254 167 170 159 -238 3 0 256 171 174 162 -239 3 0 258 175 178 238 -240 3 0 260 179 182 165 -241 3 0 300 250 249 293 -242 3 0 101 37 38 302 -243 3 0 105 53 54 304 -244 3 0 81 20 21 306 -245 3 0 111 5 6 308 -246 3 0 65 68 126 71 -247 3 0 69 71 126 128 -248 3 0 298 343 75 74 -249 3 0 76 199 299 166 -250 3 0 278 244 72 150 -251 3 0 153 282 348 154 -252 3 0 247 78 151 286 -253 3 0 290 349 156 155 -254 3 0 325 324 327 333 -255 3 0 188 325 333 239 -256 3 0 280 255 158 277 -257 3 0 257 161 281 284 -258 3 0 259 242 285 288 -259 3 0 261 164 289 292 -260 3 0 67 294 127 68 -261 3 0 188 239 92 189 -262 3 0 191 149 130 96 -263 3 0 184 328 326 185 -264 3 0 346 240 241 329 -265 3 0 262 99 255 280 -266 3 0 103 257 284 266 -267 3 0 109 261 292 273 -268 3 0 55 56 202 351 -269 3 0 39 40 204 352 -270 3 0 236 353 24 25 -271 3 0 7 8 200 354 -272 3 0 264 229 355 336 -273 3 0 264 263 228 229 -274 3 0 356 340 271 232 -275 3 0 227 357 338 268 -276 3 0 114 232 271 115 -277 3 0 227 268 267 226 -278 3 0 275 231 358 342 -279 3 0 275 274 230 231 -280 3 0 316 283 282 153 -281 3 0 279 278 150 314 -282 3 0 291 290 155 318 -283 3 0 287 286 151 116 -284 3 0 19 339 137 18 -285 3 0 3 341 138 2 -286 3 0 16 137 340 356 -287 3 0 335 139 34 35 -288 3 0 51 337 140 50 -289 3 0 139 336 355 32 -290 3 0 342 358 64 138 -291 3 0 357 48 140 338 -292 3 0 329 241 207 323 -293 3 0 128 126 125 350 -294 3 0 128 350 222 129 -295 3 0 208 118 224 331 -296 3 0 209 122 225 332 -297 3 0 335 35 36 320 -298 3 0 52 321 337 51 -299 3 0 19 20 80 339 -300 3 0 4 322 341 3 -301 3 0 31 32 355 229 -302 3 0 16 356 232 15 -303 3 0 227 47 48 357 -304 3 0 231 63 64 358 -305 3 0 309 270 272 107 -306 3 0 214 277 158 157 -307 3 0 160 217 281 161 -308 3 0 220 248 285 242 -309 3 0 163 223 289 164 -310 3 0 265 100 99 262 -311 3 0 104 103 266 269 -312 3 0 82 107 272 80 -313 3 0 110 109 273 276 -314 3 0 265 264 336 320 -315 3 0 269 268 338 321 -316 3 0 80 272 271 340 -317 3 0 276 275 342 322 -318 3 0 310 352 204 168 -319 3 0 311 351 202 172 -320 3 0 236 176 312 353 -321 3 0 354 200 180 313 -322 3 0 38 39 352 310 -323 3 0 54 55 351 311 -324 3 0 353 312 23 24 -325 3 0 7 354 313 6 -$EndElements