From 5e35b9ddbac892221d723e6ad644ed1442d1f467 Mon Sep 17 00:00:00 2001 From: Linus Seelinger <S.Linus@gmx.de> Date: Fri, 1 Jul 2016 17:04:32 +0200 Subject: [PATCH] [lib][factory] Introduce ISTL library with preinstantiated solvers to speed up compile times --- cmake/modules/DuneIstlMacros.cmake | 104 +++++++++++++++++++++++++++++ cmake/modules/solvertemplates.cc | 55 +++++++++++++++ cmake/modules/solvertemplates.hh | 59 ++++++++++++++++ config.h.cmake | 3 + 4 files changed, 221 insertions(+) create mode 100644 cmake/modules/solvertemplates.cc create mode 100644 cmake/modules/solvertemplates.hh diff --git a/cmake/modules/DuneIstlMacros.cmake b/cmake/modules/DuneIstlMacros.cmake index 1e61bc662..145f3b7d1 100644 --- a/cmake/modules/DuneIstlMacros.cmake +++ b/cmake/modules/DuneIstlMacros.cmake @@ -2,6 +2,25 @@ # # This modules content is executed whenever a module required or suggests dune-istl! # +# .. cmake_function:: dune_add_istl_library +# +# .. cmake_brief:: +# +# Adds a library with precompiled preconditioners and solvers +# +# .. cmake_param:: BLOCKSIZES +# :multi: +# +# The block sizes of vectors/matrices used in your module +# +# +# This function adds a library to the user's dune module which contains precompiled +# preconditioners and solvers. This allows for faster compilation of the actual module. +# This pays off especially when using a factory to create preconditioners and solvers +# dynamically. +# The vector/matrix block sizes used in your module must be passed in order for the +# precompiled preconditioners and solvers to be used. + find_package(METIS) find_package(ParMETIS) @@ -12,3 +31,88 @@ find_package(ARPACKPP) include(AddARPACKPPFlags) find_package(SuiteSparse OPTIONAL_COMPONENTS LDL SPQR UMFPACK) include(AddSuiteSparseFlags) + + +# We always have to write the header because it will always be included +file(WRITE ${CMAKE_BINARY_DIR}/solvertemplates.hh "// Placeholder for istl library includes\n") + +set (DUNE_ADD_ISTL_LIBRARY_CALLED 0 CACHE INTERNAL "") + + +# Allow including a library for precompiled preconditioners / solvers +function(dune_add_istl_library) + + cmake_minimum_required(VERSION 3.1) + + # Only allow this to be called once + if (DUNE_ADD_ISTL_LIBRARY_CALLED) + message(FATAL_ERROR "You may only call dune_add_istl_library once per module!") + endif() + set (DUNE_ADD_ISTL_LIBRARY_CALLED 1 CACHE INTERNAL "") + + # Set library name from current module name + string(REGEX REPLACE "[^a-zA-Z0-9-]" "_" safe_proj_name ${CMAKE_PROJECT_NAME}) + set(libname ${safe_proj_name}-istl) + + # Check if listed in dune_enable_all_packages + set (found -1) + if (DUNE_ENABLE_ALL_PACKAGES_MODULE_LIBRARIES) + foreach(module_lib ${DUNE_ENABLE_ALL_PACKAGES_MODULE_LIBRARIES}) + if (${module_lib} STREQUAL ${libname}) + set (found 1) + break() + endif() + endforeach() + endif() + if (${found} EQUAL -1) + message(FATAL_ERROR "You have to register ${libname} as a module library in dune_enable_all_packages before calling dune_add_istl_library!") + endif() + + + + # Parse input + include(CMakeParseArguments) + set(MULTIARGS BLOCKSIZES) + cmake_parse_arguments(ADDLIB "" "" "${MULTIARGS}" ${ARGN}) + + # Check whether the parser produced any errors + if(ADDLIB_UNPARSED_ARGUMENTS) + message(WARNING "Unrecognized arguments ('${ADDLIB_UNPARSED_ARGUMENTS}') for dune_add_istl_library!") + endif() + + # Check BLOCKSIZES for correctness + if(NOT ADDLIB_BLOCKSIZES) + message(FATAL_ERROR "BLOCKSIZES has to be specified!") + endif() + foreach(bs ${ADDLIB_BLOCKSIZES}) + if(NOT "${bs}" MATCHES "[1-9][0-9]*") + message(FATAL_ERROR "${bs} was given to the BLOCKSIZES arugment of dune_add_istl_library, but it does not seem like a correct block size number") + endif() + endforeach() + + + + # Get module path of istl + dune_module_path(MODULE dune-istl RESULT moddir CMAKE_MODULES) + + # Generate template instantiation headers and cc's + file(WRITE ${CMAKE_BINARY_DIR}/solvertemplates.cc "// Auto-generated template stuff\n") + file(WRITE ${CMAKE_BINARY_DIR}/solvertemplates.hh "// Auto-generated template stuff\n") + foreach(bs ${ADDLIB_BLOCKSIZES}) + set(BLOCKSIZE ${bs}) + configure_file("${moddir}/solvertemplates.hh" ${CMAKE_BINARY_DIR}/solvertemplates${bs}.hh) + configure_file("${moddir}/solvertemplates.cc" ${CMAKE_BINARY_DIR}/solvertemplates${bs}.cc) + + file(APPEND ${CMAKE_BINARY_DIR}/solvertemplates.cc "#include \"solvertemplates${bs}.cc\"\n") + file(APPEND ${CMAKE_BINARY_DIR}/solvertemplates.hh "#include \"solvertemplates${bs}.hh\"\n") + + endforeach() + include_directories(${CMAKE_BINARY_DIR}) + + + + # Build library + dune_library_add_sources(${libname} SOURCES ${CMAKE_BINARY_DIR}/solvertemplates.cc) + + +endfunction() diff --git a/cmake/modules/solvertemplates.cc b/cmake/modules/solvertemplates.cc new file mode 100644 index 000000000..3c763c2db --- /dev/null +++ b/cmake/modules/solvertemplates.cc @@ -0,0 +1,55 @@ +#include <config.h> +#include <dune/istl/bvector.hh> +#include <dune/istl/bcrsmatrix.hh> +#include <dune/common/parallel/indexset.hh> +#include <dune/istl/paamg/pinfo.hh> +#include <dune/istl/paamg/amg.hh> +#include <dune/istl/owneroverlapcopy.hh> // For instantiation of parallel factories +#include <dune/istl/factory.hh> + +namespace Dune { + +#if HAVE_MPI + + namespace Precomp${BLOCKSIZE} { + + typedef Dune::BlockVector<Dune::FieldVector<double,${BLOCKSIZE}> > V; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<double,${BLOCKSIZE},${BLOCKSIZE}> > M; + typedef OwnerOverlapCopyCommunication<int> COMM; + + typedef Dune::OverlappingSchwarzOperator<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::COMM> Operator1; + typedef Dune::SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> Smoother1; + typedef Dune::BlockPreconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::COMM,Smoother1> ParSmoother1; + + } + template class Amg::AMG<Precomp${BLOCKSIZE}::Operator1,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::ParSmoother1,Precomp${BLOCKSIZE}::COMM>; + + template std::shared_ptr<InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverPrecondFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::COMM, Precomp${BLOCKSIZE}::M>(const Precomp${BLOCKSIZE}::M& A, const Precomp${BLOCKSIZE}::COMM& comm, ParameterTree& configuration, std::string group); + template std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::PreconditionerFactory::create<Precomp${BLOCKSIZE}::COMM, Precomp${BLOCKSIZE}::M, Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::V>(std::string id, const Precomp${BLOCKSIZE}::M& A, const ParameterTree& configuration, const Precomp${BLOCKSIZE}::COMM& comm, std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> >& out_linearoperator); + template std::shared_ptr<InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverFactory::create<Precomp${BLOCKSIZE}::V>(std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > linearoperator, std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > preconditioner, std::string id, const ParameterTree& configuration, const Precomp${BLOCKSIZE}::COMM& comm); + +#endif + + template std::shared_ptr<Dune::InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverPrecondFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::M>(const Precomp${BLOCKSIZE}::M& A, ParameterTree& configuration, std::string group); + template std::shared_ptr<Dune::Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::PreconditionerFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::M>(std::string id, const Precomp${BLOCKSIZE}::M& A, const ParameterTree& configuration); + template std::shared_ptr<Dune::InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverFactory::create<Precomp${BLOCKSIZE}::V>(std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > linearoperator, std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > preconditioner, std::string id, const ParameterTree& configuration); + + + template class Dune::BiCGSTABSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::CGSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::GeneralizedPCGSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::GradientSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::LoopSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::MINRESSolver<Precomp${BLOCKSIZE}::V>; + template class Dune::RestartedGMResSolver<Precomp${BLOCKSIZE}::V>; + + template class Amg::AMG<MatrixOperator<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>,Precomp${BLOCKSIZE}::V,SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> >; + template class Dune::Richardson<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqGS<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqILU0<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqILUn<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqJac<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + template class Dune::SeqSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + +} diff --git a/cmake/modules/solvertemplates.hh b/cmake/modules/solvertemplates.hh new file mode 100644 index 000000000..a771680c4 --- /dev/null +++ b/cmake/modules/solvertemplates.hh @@ -0,0 +1,59 @@ +#include <dune/istl/bvector.hh> +#include <dune/istl/bcrsmatrix.hh> +#include <dune/common/parallel/indexset.hh> +#include <dune/istl/paamg/pinfo.hh> +#include <dune/istl/paamg/amg.hh> +#include <dune/istl/owneroverlapcopy.hh> // For instantiation of parallel factories +#include <dune/istl/factory.hh> + +#ifndef DUNE_ISTL_SOLVERTEMPLATES${BLOCKSIZE}_HH +#define DUNE_ISTL_SOLVERTEMPLATES${BLOCKSIZE}_HH + +namespace Dune { + +#if HAVE_MPI + + namespace Precomp${BLOCKSIZE} { + + typedef Dune::BlockVector<Dune::FieldVector<double,${BLOCKSIZE}> > V; + typedef Dune::BCRSMatrix<Dune::FieldMatrix<double,${BLOCKSIZE},${BLOCKSIZE}> > M; + typedef OwnerOverlapCopyCommunication<int> COMM; + + typedef Dune::OverlappingSchwarzOperator<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::COMM> Operator1; + typedef Dune::SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> Smoother1; + typedef Dune::BlockPreconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::COMM,Smoother1> ParSmoother1; + + } + extern template class Amg::AMG<Precomp${BLOCKSIZE}::Operator1,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::ParSmoother1,Precomp${BLOCKSIZE}::COMM>; + + extern template std::shared_ptr<InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverPrecondFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::COMM, Precomp${BLOCKSIZE}::M>(const Precomp${BLOCKSIZE}::M& A, const Precomp${BLOCKSIZE}::COMM& comm, ParameterTree& configuration, std::string group); + extern template std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::PreconditionerFactory::create<Precomp${BLOCKSIZE}::COMM, Precomp${BLOCKSIZE}::M, Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::V>(std::string id, const Precomp${BLOCKSIZE}::M& A, const ParameterTree& configuration, const Precomp${BLOCKSIZE}::COMM& comm, std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> >& out_linearoperator); + extern template std::shared_ptr<InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverFactory::create<Precomp${BLOCKSIZE}::V>(std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > linearoperator, std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > preconditioner, std::string id, const ParameterTree& configuration, const Precomp${BLOCKSIZE}::COMM& comm); + +#endif + + extern template std::shared_ptr<Dune::InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverPrecondFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::M>(const Precomp${BLOCKSIZE}::M& A, ParameterTree& configuration, std::string group); + extern template std::shared_ptr<Dune::Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::PreconditionerFactory::create<Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::V, Precomp${BLOCKSIZE}::M>(std::string id, const Precomp${BLOCKSIZE}::M& A, const ParameterTree& configuration); + extern template std::shared_ptr<Dune::InverseOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > Dune::SolverFactory::create<Precomp${BLOCKSIZE}::V>(std::shared_ptr<LinearOperator<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > linearoperator, std::shared_ptr<Preconditioner<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> > preconditioner, std::string id, const ParameterTree& configuration); + + + extern template class Dune::BiCGSTABSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::CGSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::GeneralizedPCGSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::GradientSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::LoopSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::MINRESSolver<Precomp${BLOCKSIZE}::V>; + extern template class Dune::RestartedGMResSolver<Precomp${BLOCKSIZE}::V>; + + extern template class Amg::AMG<MatrixOperator<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>,Precomp${BLOCKSIZE}::V,SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V> >; + extern template class Dune::Richardson<Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqGS<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqILU0<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqILUn<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqJac<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqSSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + extern template class Dune::SeqSOR<Precomp${BLOCKSIZE}::M,Precomp${BLOCKSIZE}::V,Precomp${BLOCKSIZE}::V>; + +} + +#endif diff --git a/config.h.cmake b/config.h.cmake index 3c488a94a..6845e4e5e 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -71,6 +71,9 @@ /* Define to the revision of dune-istl */ #define DUNE_ISTL_VERSION_REVISION ${DUNE_ISTL_VERSION_REVISION} +/* Includes for istl library */ +#include "solvertemplates.hh" + /* end dune-istl Everything below here will be overwritten */ -- GitLab