From 2a75edee4e5b6db607c4db4abd02a7504694482e Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Mon, 9 Jan 2017 14:44:33 +0100 Subject: [PATCH] Implement function to check for MatrixFree support --- doc/news/changes/minor/20170111DanielArndt | 3 + include/deal.II/matrix_free/matrix_free.h | 7 ++ .../matrix_free/matrix_free.templates.h | 32 +++++++ .../deal.II/numerics/vector_tools.templates.h | 33 ++----- source/matrix_free/matrix_free.inst.in | 13 ++- tests/matrix_free/is_supported_01.cc | 90 +++++++++++++++++++ tests/matrix_free/is_supported_01.output | 29 ++++++ 7 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 doc/news/changes/minor/20170111DanielArndt create mode 100644 tests/matrix_free/is_supported_01.cc create mode 100644 tests/matrix_free/is_supported_01.output diff --git a/doc/news/changes/minor/20170111DanielArndt b/doc/news/changes/minor/20170111DanielArndt new file mode 100644 index 0000000000..214782d0bb --- /dev/null +++ b/doc/news/changes/minor/20170111DanielArndt @@ -0,0 +1,3 @@ +New: MatrixFree allows to be asked if a certain FiniteElement is supported. +
+(Daniel Arndt, 2017/01/11) diff --git a/include/deal.II/matrix_free/matrix_free.h b/include/deal.II/matrix_free/matrix_free.h index a3e0d1d37b..0bf111a6cb 100644 --- a/include/deal.II/matrix_free/matrix_free.h +++ b/include/deal.II/matrix_free/matrix_free.h @@ -639,6 +639,13 @@ public: * @name 4: General information */ //@{ + /** + * Returns whether a given FiniteElement @p fe is supported by this class. + */ + template + static + bool is_supported (const FiniteElement &fe); + /** * Return the number of different DoFHandlers specified at initialization. */ diff --git a/include/deal.II/matrix_free/matrix_free.templates.h b/include/deal.II/matrix_free/matrix_free.templates.h index 67e5a93344..e30047393b 100644 --- a/include/deal.II/matrix_free/matrix_free.templates.h +++ b/include/deal.II/matrix_free/matrix_free.templates.h @@ -331,6 +331,38 @@ internal_reinit(const Mapping &mapping, } +template +template +bool +MatrixFree::is_supported(const FiniteElement &fe) +{ + if (dim != spacedim) + return false; + + // first check for degree, number of base_elemnt and number of its components + if (fe.degree==0 || fe.n_base_elements()!=1) + return false; + + const FiniteElement *fe_ptr = &(fe.base_element(0)); + if (fe_ptr->n_components() != 1) + return false; + + // then check of the base element is supported + if (dynamic_cast,dim,spacedim>*>(fe_ptr)!=0) + return true; + if (dynamic_cast >,dim,spacedim>*>(fe_ptr)!=0) + return true; + if (dynamic_cast*>(fe_ptr)!=0) + return true; + if (dynamic_cast*>(fe_ptr)!=0) + return true; + + // if the base element is not in the above list it is not supported + return false; +} + + namespace internal { diff --git a/include/deal.II/numerics/vector_tools.templates.h b/include/deal.II/numerics/vector_tools.templates.h index 920d959b71..0b64ae5dc3 100644 --- a/include/deal.II/numerics/vector_tools.templates.h +++ b/include/deal.II/numerics/vector_tools.templates.h @@ -1113,34 +1113,15 @@ namespace VectorTools const bool project_to_boundary_first) { // If we can, use the matrix-free implementation - bool use_matrix_free = true; + bool use_matrix_free = MatrixFree::is_supported(dof.get_fe()); + // enforce_zero_boundary and project_to_boundary_first - // are not yet supported - if (enforce_zero_boundary || project_to_boundary_first) + // are not yet supported. + // We have explicit instantiations only if + // the number of components and the degree is not too high. + if (enforce_zero_boundary || project_to_boundary_first + || dof.get_fe().degree>8 || dof.get_fe().n_components()>4) use_matrix_free = false; - else - { - // Find out if the FiniteElement is supported - // This is based on matrix_free/shape_info.templates.h - // and matrix_free/matrix_free.templates.h - if (dof.get_fe().degree==0 || dof.get_fe().n_base_elements()!=1 - || dof.get_fe().degree>8 || dof.get_fe().n_components()>4) - use_matrix_free = false; - else - { - const FiniteElement *fe_ptr = &dof.get_fe().base_element(0); - if (fe_ptr->n_components() != 1) - use_matrix_free = false; - else if ((dynamic_cast,dim,dim>*>(fe_ptr)==0) - && (dynamic_cast >,dim,dim>*>(fe_ptr)==0) - &&(dynamic_cast*>(fe_ptr)==0) - &&(dynamic_cast*>(fe_ptr)==0) - &&(dynamic_cast*>(fe_ptr)==0) - &&(dynamic_cast*>(fe_ptr)==0)) - use_matrix_free = false; - } - } if (use_matrix_free) project_matrix_free_component (mapping, dof, constraints, quadrature, diff --git a/source/matrix_free/matrix_free.inst.in b/source/matrix_free/matrix_free.inst.in index aaa35c70c8..fe24f54f21 100644 --- a/source/matrix_free/matrix_free.inst.in +++ b/source/matrix_free/matrix_free.inst.in @@ -1,6 +1,6 @@ // --------------------------------------------------------------------- // -// Copyright (C) 2010 - 2016 by the deal.II authors +// Copyright (C) 2010 - 2017 by the deal.II authors // // This file is part of the deal.II library. // @@ -41,3 +41,14 @@ for (deal_II_dimension : DIMENSIONS) &, const unsigned int); #endif } + +for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS) +{ +#if deal_II_dimension <= deal_II_space_dimension + template bool MatrixFree:: + is_supported(const FiniteElement &); + + template bool MatrixFree:: + is_supported(const FiniteElement &); +#endif +} diff --git a/tests/matrix_free/is_supported_01.cc b/tests/matrix_free/is_supported_01.cc new file mode 100644 index 0000000000..19a368a3fe --- /dev/null +++ b/tests/matrix_free/is_supported_01.cc @@ -0,0 +1,90 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +// Test the ouput of MatrixFree::is_supported for various FiniteElements + +#include "../tests.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +template +void print(const FiniteElement &fe) +{ + deallog << fe.get_name() << " supported by MatrixFree: " + << std::boolalpha << MatrixFree::is_supported(fe) + << std::endl; +} + + +int main () +{ + initlog(); + + print<2,2> (FE_ABF<2>(0)); + print<2,2> (FE_BDM<2>(1)); + print<2,2> (FE_Bernstein<2>(1)); + print<2,2> (FE_DGBDM<2>(1)); + print<2,2> (FE_DGNedelec<2>(1)); + print<1,2> (FE_DGP<1,2>(1)); + print<2,2> (FE_DGP<2>(1)); + print<2,2> (FE_DGPMonomial<2>(1)); + print<2,2> (FE_DGPNonparametric<2>(1)); + print<2,2> (FE_DGRaviartThomas<2>(1)); + print<1,2> (FE_DGQ<1,2>(1)); + print<2,2> (FE_DGQ<2>(1)); + print<2,2> (FE_DGQArbitraryNodes<2>(QGauss<1>(2))); + print<2,2> (FE_FaceP<2>(1)); + print<2,2> (FE_FaceQ<2>(1)); + print<2,2> (FE_P1NC()); + print<2,2> (FE_Nedelec<2>(1)); + print<2,2> (FE_Nothing<2>()); + print<1,2> (FE_Q<1,2>(1)); + print<2,2> (FE_Q<2>(1)); + print<2,2> (FE_Q_Bubbles<2>(1)); + print<2,2> (FE_Q_DG0<2>(1)); + print<2,2> (FE_Q_Hierarchical<2>(1)); + print<2,2> (FE_Q_iso_Q1<2>(1)); + print<2,2> (FE_RannacherTurek<2>(0)); + print<2,2> (FE_RaviartThomas<2>(1)); + print<2,2> (FE_RaviartThomasNodal<2>(1)); + print<2,2> (FE_TraceQ<2>(1)); + + return 0; +} diff --git a/tests/matrix_free/is_supported_01.output b/tests/matrix_free/is_supported_01.output new file mode 100644 index 0000000000..2601ac3def --- /dev/null +++ b/tests/matrix_free/is_supported_01.output @@ -0,0 +1,29 @@ + +DEAL::FE_ABF<2>(0) supported by MatrixFree: false +DEAL::FE_BDM<2>(1) supported by MatrixFree: false +DEAL::FE_Bernstein<2>(1) supported by MatrixFree: true +DEAL::FE_DGBDM<2>(1) supported by MatrixFree: false +DEAL::FE_DGNedelec<2>(1) supported by MatrixFree: false +DEAL::FE_DGP<1,2>(1) supported by MatrixFree: false +DEAL::FE_DGP<2>(1) supported by MatrixFree: true +DEAL::FE_DGPMonomial<2>(1) supported by MatrixFree: false +DEAL::FE_DGPNonparametric<2>(1) supported by MatrixFree: false +DEAL::FE_DGRaviartThomas<2>(1) supported by MatrixFree: false +DEAL::FE_DGQ<1,2>(1) supported by MatrixFree: false +DEAL::FE_DGQ<2>(1) supported by MatrixFree: true +DEAL::FE_DGQArbitraryNodes<2>(QGauss(2)) supported by MatrixFree: true +DEAL::FE_FaceP<2>(1) supported by MatrixFree: false +DEAL::FE_FaceQ<2>(1) supported by MatrixFree: false +DEAL::FE_P1NC supported by MatrixFree: false +DEAL::FE_Nedelec<2>(1) supported by MatrixFree: false +DEAL::FE_Nothing<2>() supported by MatrixFree: false +DEAL::FE_Q<1,2>(1) supported by MatrixFree: false +DEAL::FE_Q<2>(1) supported by MatrixFree: true +DEAL::FE_Q_Bubbles<2>(1) supported by MatrixFree: false +DEAL::FE_Q_DG0<2>(1) supported by MatrixFree: true +DEAL::FE_Q_Hierarchical<2>(1) supported by MatrixFree: true +DEAL::FE_Q_iso_Q1<2>(1) supported by MatrixFree: true +DEAL::FE_RannacherTurek<2>(0, 2) supported by MatrixFree: false +DEAL::FE_RaviartThomas<2>(1) supported by MatrixFree: false +DEAL::FE_RaviartThomasNodal<2>(1) supported by MatrixFree: false +DEAL::FE_TraceQ<2>(1) supported by MatrixFree: false -- 2.39.5