From f77a9fbee1b5685092cead4426297ff37f70e20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20He=C3=9F?= <rene.hess@iwr.uni-heidelberg.de> Date: Thu, 24 Nov 2016 17:22:42 +0100 Subject: [PATCH] 3D sumfactorized poisson --- python/dune/perftool/loopy/buffer.py | 10 +++++++++- python/dune/perftool/sumfact/basis.py | 20 +++++++++++++++----- python/dune/perftool/sumfact/sumfact.py | 17 ++++++++++++----- test/sumfact/mass/CMakeLists.txt | 5 +++++ test/sumfact/mass/mass_3d.mini | 19 +++++++++++++++++++ test/sumfact/mass/mass_3d.ufl | 10 ++++++++++ test/sumfact/poisson/CMakeLists.txt | 11 +++++++++++ test/sumfact/poisson/poisson_3d_order1.mini | 20 ++++++++++++++++++++ test/sumfact/poisson/poisson_3d_order1.ufl | 10 ++++++++++ test/sumfact/poisson/poisson_3d_order2.mini | 20 ++++++++++++++++++++ test/sumfact/poisson/poisson_3d_order2.ufl | 10 ++++++++++ 11 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 test/sumfact/mass/mass_3d.mini create mode 100644 test/sumfact/mass/mass_3d.ufl create mode 100644 test/sumfact/poisson/poisson_3d_order1.mini create mode 100644 test/sumfact/poisson/poisson_3d_order1.ufl create mode 100644 test/sumfact/poisson/poisson_3d_order2.mini create mode 100644 test/sumfact/poisson/poisson_3d_order2.ufl diff --git a/python/dune/perftool/loopy/buffer.py b/python/dune/perftool/loopy/buffer.py index e7207c2b..d7e6c97a 100644 --- a/python/dune/perftool/loopy/buffer.py +++ b/python/dune/perftool/loopy/buffer.py @@ -1,5 +1,6 @@ from dune.perftool.error import PerftoolLoopyError from dune.perftool.generation import (generator_factory, + get_global_context_value, temporary_variable, ) @@ -33,10 +34,17 @@ class FlipFlopBuffer(object): name = "{}_{}".format(self.identifier, self._counter) self._counter = self._counter + 1 + # Get geometric dimension + formdata = get_global_context_value('formdata') + dim = formdata.geometric_dimension + + # TODO: doc! + storage_shape = (self.base_storage_size,) + (1,)*(dim-1) + # Construct the temporary and return it temporary_variable(name, base_storage=base, - storage_shape=(self.base_storage_size, 1), + storage_shape=storage_shape, managed=True, **kwargs ) diff --git a/python/dune/perftool/sumfact/basis.py b/python/dune/perftool/sumfact/basis.py index 0af2d38c..03665d47 100644 --- a/python/dune/perftool/sumfact/basis.py +++ b/python/dune/perftool/sumfact/basis.py @@ -3,6 +3,7 @@ NB: Basis evaluation is only needed for the trial function argument in jacobians, as the multiplication with the test function is part of the sum factorization kernel. """ + from dune.perftool.generation import (backend, domain, get_counter, @@ -69,13 +70,15 @@ def sumfact_evaluate_coefficient_gradient(element, name, restriction, component) a_matrices[i] = dtheta_matrix a_matrices = tuple(a_matrices) - # Do stage 1 buffer_name = name_sumfact_base_buffer() initialize_buffer(buffer_name, base_storage_size=product(max(mat.rows, mat.cols) for mat in a_matrices), num=2 ) + # Add a sum factorization kernel that implements the + # evaluation of the gradients of basis functions at quadrature + # points (stage 1) insn_dep = setup_theta(element, restriction, component, a_matrices, buffer_name) var, _ = sum_factorization_kernel(a_matrices, buffer_name, @@ -110,20 +113,26 @@ def pymbolic_trialfunction_gradient(element, restriction, component): @kernel_cached def pymbolic_trialfunction(element, restriction, component): + # Get geometric dimension + formdata = get_global_context_value('formdata') + dim = formdata.geometric_dimension + + # Setup sumfactorization theta = name_theta() rows = quadrature_points_per_direction() cols = basis_functions_per_direction() a_matrix = AMatrix(theta, rows, cols) - # TODO: this is 2D only - a_matrices = (a_matrix, a_matrix) - buffer_name = name_sumfact_base_buffer() + a_matrices = (a_matrix,)*dim - # Do stage 1 + # Flip flop buffers for sumfactorization + buffer_name = name_sumfact_base_buffer() initialize_buffer(buffer_name, base_storage_size=product(max(mat.rows, mat.cols) for mat in a_matrices), num=2 ) + # Add a sum factorization kernel that implements the evaluation of + # the basis functions at quadrature points (stage 1) insn_dep = setup_theta(element, restriction, component, a_matrices, buffer_name) var, _ = sum_factorization_kernel(a_matrices, buffer_name, @@ -193,6 +202,7 @@ def evaluate_reference_gradient(element, name, restriction): inames = lfs_inames(element, restriction) assert(len(quad_inames) == len(inames)) + # Matrices for sumfactorization theta = name_theta() dtheta = name_dtheta() diff --git a/python/dune/perftool/sumfact/sumfact.py b/python/dune/perftool/sumfact/sumfact.py index 36240228..04a18a7b 100644 --- a/python/dune/perftool/sumfact/sumfact.py +++ b/python/dune/perftool/sumfact/sumfact.py @@ -32,6 +32,7 @@ from dune.perftool.pdelab.restriction import restricted_name from dune.perftool.pdelab.spaces import name_lfs from dune.perftool.sumfact.amatrix import (AMatrix, quadrature_points_per_direction, + name_dtheta_transposed, basis_functions_per_direction, name_theta, name_theta_transposed, @@ -124,7 +125,6 @@ def generate_accumulation_instruction(visitor, accterm, measure, subdomain_id): # If this is a gradient we need different matrices if accterm.argument.index: - from dune.perftool.sumfact.amatrix import name_dtheta_transposed dtheta_transposed = name_dtheta_transposed() rows = basis_functions_per_direction() cols = quadrature_points_per_direction() @@ -135,13 +135,14 @@ def generate_accumulation_instruction(visitor, accterm, measure, subdomain_id): a_matrices = tuple(a_matrices) else: - a_matrices = (theta_matrix, theta_matrix) + a_matrices = (theta_matrix,)*dim + # Initialize a base storage for this buffer and get a temporay pointing to it temp = initialize_buffer(buf, base_storage_size=product(max(mat.rows, mat.cols) for mat in a_matrices), num=2 ).get_temporary(shape=(quadrature_points_per_direction(),) * dim, - dim_tags="f,f") + dim_tags=",".join(['f']*dim)) # Replace gradient iname with correct index for assignement replace_dict = {} @@ -162,7 +163,7 @@ def generate_accumulation_instruction(visitor, accterm, measure, subdomain_id): contribution_ids.append(contrib_dep) # Add a sum factorization kernel that implements the multiplication - # with the test function (step 3) + # with the test function (stage 3) result, insn_dep = sum_factorization_kernel(a_matrices, buf, insn_dep=frozenset({contrib_dep}), @@ -274,9 +275,15 @@ def sum_factorization_kernel(a_matrices, buf, insn_dep=frozenset({}), additional ) }) + # Get geometric dimension + formdata = get_global_context_value('formdata') + dim = formdata.geometric_dimension + + out_shape = tuple(mat.rows for mat in a_matrices) + dim_tags = ",".join(['f']*dim) out = get_buffer_temporary(buf, shape=out_shape, - dim_tags="f,f") + dim_tags=dim_tags) silenced_warning('read_no_write({})'.format(out)) return out, insn_dep diff --git a/test/sumfact/mass/CMakeLists.txt b/test/sumfact/mass/CMakeLists.txt index a3357bef..a640f020 100644 --- a/test/sumfact/mass/CMakeLists.txt +++ b/test/sumfact/mass/CMakeLists.txt @@ -3,3 +3,8 @@ dune_add_formcompiler_system_test(UFLFILE mass.ufl BASENAME sumfact_mass INIFILE mass.mini ) + +dune_add_formcompiler_system_test(UFLFILE mass_3d.ufl + BASENAME sumfact_mass_3d + INIFILE mass_3d.mini + ) diff --git a/test/sumfact/mass/mass_3d.mini b/test/sumfact/mass/mass_3d.mini new file mode 100644 index 00000000..17da3e4f --- /dev/null +++ b/test/sumfact/mass/mass_3d.mini @@ -0,0 +1,19 @@ +__name = sumfact_mass_3d_{__exec_suffix} +__exec_suffix = {diff_suffix}_{vec_suffix} + +diff_suffix = numdiff, symdiff | expand num +vec_suffix = vec, nonvec | expand vec + +cells = 1 1 1 +extension = 1. 1. 1. + +printmatrix = true + +[wrapper.vtkcompare] +name = {__name} +extension = vtu + +[formcompiler] +numerical_jacobian = 1, 0 | expand num +vectorize = 1, 0 | expand vec +sumfact = 1 diff --git a/test/sumfact/mass/mass_3d.ufl b/test/sumfact/mass/mass_3d.ufl new file mode 100644 index 00000000..bd56d296 --- /dev/null +++ b/test/sumfact/mass/mass_3d.ufl @@ -0,0 +1,10 @@ +cell = "hexahedron" + +V = FiniteElement("DG", cell, 1) + +u = TrialFunction(V) +v = TestFunction(V) + +r = u * v * dx + +forms = [r] diff --git a/test/sumfact/poisson/CMakeLists.txt b/test/sumfact/poisson/CMakeLists.txt index 74cce96e..70a9791a 100644 --- a/test/sumfact/poisson/CMakeLists.txt +++ b/test/sumfact/poisson/CMakeLists.txt @@ -11,6 +11,17 @@ dune_add_formcompiler_system_test(UFLFILE poisson_order2.ufl INIFILE poisson_order2.mini ) +# 3D Test cases +dune_add_formcompiler_system_test(UFLFILE poisson_3d_order1.ufl + BASENAME sumfact_poisson_3d_order1 + INIFILE poisson_3d_order1.mini + ) +dune_add_formcompiler_system_test(UFLFILE poisson_3d_order2.ufl + BASENAME sumfact_poisson_3d_order2 + INIFILE poisson_3d_order2.mini + ) + + # # 2. Poisson Test Case: DG, f + pure dirichlet # dune_add_formcompiler_system_test(UFLFILE poisson_dg.ufl # BASENAME sumfact_poisson_dg diff --git a/test/sumfact/poisson/poisson_3d_order1.mini b/test/sumfact/poisson/poisson_3d_order1.mini new file mode 100644 index 00000000..6250546e --- /dev/null +++ b/test/sumfact/poisson/poisson_3d_order1.mini @@ -0,0 +1,20 @@ +__name = sumfact_poisson_3d_order1_{__exec_suffix} +__exec_suffix = {diff_suffix}_{vec_suffix} + +diff_suffix = numdiff, symdiff | expand num +vec_suffix = vec, nonvec | expand vec + +cells = 8 8 8 +extension = 1. 1. 1. + +[wrapper.vtkcompare] +name = {__name} +reference = poisson_ref +extension = vtu + +[formcompiler] +numerical_jacobian = 1, 0 | expand num +exact_solution_expression = g +compare_l2errorsquared = 1e-4 +sumfact = 1 +vectorize = 1, 0 | expand vec diff --git a/test/sumfact/poisson/poisson_3d_order1.ufl b/test/sumfact/poisson/poisson_3d_order1.ufl new file mode 100644 index 00000000..4de9c239 --- /dev/null +++ b/test/sumfact/poisson/poisson_3d_order1.ufl @@ -0,0 +1,10 @@ +cell = "hexahedron" + +f = Expression("Dune::FieldVector<double,2> c(0.5); c-= x; return 4.*(1.-c.two_norm2())*std::exp(-1.*c.two_norm2());", cell=cell) +g = Expression("Dune::FieldVector<double,2> c(0.5); c-= x; return std::exp(-1.*c.two_norm2());", cell=cell) + +V = FiniteElement("CG", cell, 1, dirichlet_expression=g) +u = TrialFunction(V) +v = TestFunction(V) + +forms = [(inner(grad(u), grad(v)) - f*v)*dx] diff --git a/test/sumfact/poisson/poisson_3d_order2.mini b/test/sumfact/poisson/poisson_3d_order2.mini new file mode 100644 index 00000000..2db0990d --- /dev/null +++ b/test/sumfact/poisson/poisson_3d_order2.mini @@ -0,0 +1,20 @@ +__name = sumfact_poisson_3d_order2_{__exec_suffix} +__exec_suffix = {diff_suffix}_{vec_suffix} + +diff_suffix = numdiff, symdiff | expand num +vec_suffix = vec, nonvec | expand vec + +cells = 8 8 8 +extension = 1. 1. 1. + +[wrapper.vtkcompare] +name = {__name} +reference = poisson_ref +extension = vtu + +[formcompiler] +numerical_jacobian = 1, 0 | expand num +exact_solution_expression = g +compare_l2errorsquared = 1e-4 +sumfact = 1 +vectorize = 1, 0 | expand vec diff --git a/test/sumfact/poisson/poisson_3d_order2.ufl b/test/sumfact/poisson/poisson_3d_order2.ufl new file mode 100644 index 00000000..66870b07 --- /dev/null +++ b/test/sumfact/poisson/poisson_3d_order2.ufl @@ -0,0 +1,10 @@ +cell = "hexahedron" + +f = Expression("Dune::FieldVector<double,2> c(0.5); c-= x; return 4.*(1.-c.two_norm2())*std::exp(-1.*c.two_norm2());", cell=cell) +g = Expression("Dune::FieldVector<double,2> c(0.5); c-= x; return std::exp(-1.*c.two_norm2());", cell=cell) + +V = FiniteElement("CG", cell, 2, dirichlet_expression=g) +u = TrialFunction(V) +v = TestFunction(V) + +forms = [(inner(grad(u), grad(v)) - f*v)*dx] -- GitLab