From d37b378cd73f26b486796fa280eadb7d6d6f8d1c Mon Sep 17 00:00:00 2001 From: Christoph Lehmann <christoph.lehmann@ufz.de> Date: Sun, 21 Nov 2021 13:43:57 +0100 Subject: [PATCH] [PL] Unified local assembler factories for Taylor-Hood elements --- .../HydroMechanics/CreateLocalAssemblers.h | 14 +- ProcessLib/StokesFlow/CreateLocalAssemblers.h | 18 +- ProcessLib/StokesFlow/LocalDataInitializer.h | 152 ---------------- ...calAssemblerFactoryTaylorHoodForOrderGeN.h | 171 ++++++++++++++++++ ProcessLib/Utils/LocalDataInitializerHM.h | 151 ---------------- 5 files changed, 185 insertions(+), 321 deletions(-) delete mode 100644 ProcessLib/StokesFlow/LocalDataInitializer.h create mode 100644 ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h delete mode 100644 ProcessLib/Utils/LocalDataInitializerHM.h diff --git a/ProcessLib/HydroMechanics/CreateLocalAssemblers.h b/ProcessLib/HydroMechanics/CreateLocalAssemblers.h index ddbb5937fbd..af29f10bdc9 100644 --- a/ProcessLib/HydroMechanics/CreateLocalAssemblers.h +++ b/ProcessLib/HydroMechanics/CreateLocalAssemblers.h @@ -13,7 +13,7 @@ #include "BaseLib/Logging.h" #include "NumLib/DOF/LocalToGlobalIndexMap.h" -#include "ProcessLib/Utils/LocalDataInitializerHM.h" +#include "ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h" namespace ProcessLib { @@ -31,21 +31,19 @@ void createLocalAssemblers( std::vector<std::unique_ptr<LocalAssemblerInterface>>& local_assemblers, ExtraCtorArgs&&... extra_ctor_args) { - // Shape matrices initializer - using LocalDataInitializer = - LocalDataInitializerHM<LocalAssemblerInterface, - LocalAssemblerImplementation, GlobalDim, - ExtraCtorArgs...>; + using LocAsmFactory = LocalAssemblerFactoryHM<LocalAssemblerInterface, + LocalAssemblerImplementation, + GlobalDim, ExtraCtorArgs...>; DBUG("Create local assemblers."); // Populate the vector of local assemblers. local_assemblers.resize(mesh_elements.size()); - LocalDataInitializer initializer(dof_table); + LocAsmFactory factory(dof_table); DBUG("Calling local assembler builder for all mesh elements."); GlobalExecutor::transformDereferenced( - initializer, mesh_elements, local_assemblers, + factory, mesh_elements, local_assemblers, std::forward<ExtraCtorArgs>(extra_ctor_args)...); } diff --git a/ProcessLib/StokesFlow/CreateLocalAssemblers.h b/ProcessLib/StokesFlow/CreateLocalAssemblers.h index 887b298963a..e4261afda20 100644 --- a/ProcessLib/StokesFlow/CreateLocalAssemblers.h +++ b/ProcessLib/StokesFlow/CreateLocalAssemblers.h @@ -12,8 +12,8 @@ #include <vector> #include "BaseLib/Logging.h" -#include "LocalDataInitializer.h" #include "NumLib/DOF/LocalToGlobalIndexMap.h" +#include "ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h" namespace ProcessLib { @@ -31,21 +31,19 @@ void createLocalAssemblers( std::vector<std::unique_ptr<LocalAssemblerInterface>>& local_assemblers, ExtraCtorArgs&&... extra_ctor_args) { - // Shape matrices initializer - using LocalDataInitializer = - LocalDataInitializer<LocalAssemblerInterface, - LocalAssemblerImplementation, GlobalDim, - ExtraCtorArgs...>; + using LocAsmFactory = + LocalAssemblerFactoryStokes<LocalAssemblerInterface, + LocalAssemblerImplementation, GlobalDim, + ExtraCtorArgs...>; DBUG("Create local assemblers."); - // Populate the vector of local assemblers. - local_assemblers.resize(mesh_elements.size()); - LocalDataInitializer initializer(dof_table); + LocAsmFactory factory(dof_table); + local_assemblers.resize(mesh_elements.size()); DBUG("Calling local assembler builder for all mesh elements."); GlobalExecutor::transformDereferenced( - initializer, mesh_elements, local_assemblers, + factory, mesh_elements, local_assemblers, std::forward<ExtraCtorArgs>(extra_ctor_args)...); } diff --git a/ProcessLib/StokesFlow/LocalDataInitializer.h b/ProcessLib/StokesFlow/LocalDataInitializer.h deleted file mode 100644 index e317b1698a6..00000000000 --- a/ProcessLib/StokesFlow/LocalDataInitializer.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * \file - * \copyright - * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org) - * Distributed under a Modified BSD License. - * See accompanying file LICENSE.txt or - * http://www.opengeosys.org/project/license - * - */ - -#pragma once - -#include <functional> -#include <memory> -#include <type_traits> -#include <typeindex> -#include <typeinfo> -#include <unordered_map> - -#include "MeshLib/Elements/Elements.h" -#include "NumLib/DOF/LocalToGlobalIndexMap.h" -#include "NumLib/Fem/Integration/GaussLegendreIntegrationPolicy.h" -#include "ProcessLib/Utils/EnabledElements.h" - -namespace ProcessLib::StokesFlow -{ -/// The LocalDataInitializer is a functor creating a local assembler data with -/// corresponding to the mesh element type shape functions and calling -/// initialization of the new local assembler data. -/// For example for MeshLib::Quad a local assembler data with template argument -/// NumLib::ShapeQuad4 is created. -/// -/// \attention This is modified version of the ProcessLib::LocalDataInitializer -/// class which does not include line or point elements. For the shape functions -/// of order 2 (used for fluid velocity in StokesFlow) a shape function of order -/// 1 will be used for the scalar variables. -template <typename LocalAssemblerInterface, - template <typename, typename, typename, int> class LocalAssemblerData, - int GlobalDim, typename... ConstructorArgs> -class LocalDataInitializer final -{ - struct IsElementEnabled - { - template <typename ElementTraits> - constexpr bool operator()(ElementTraits*) const - { - if constexpr (GlobalDim < ElementTraits::ShapeFunction::DIM) - { - return false; - } - - return ElementTraits::Element::dimension >= 2 && - ElementTraits::ShapeFunction::ORDER == 2; - } - }; - -public: - using LADataIntfPtr = std::unique_ptr<LocalAssemblerInterface>; - - explicit LocalDataInitializer( - NumLib::LocalToGlobalIndexMap const& dof_table) - : _dof_table(dof_table) - { - using EnabledElementTraits = - decltype(BaseLib::TMP::filter<EnabledElementTraitsLagrange>( - std::declval<IsElementEnabled>())); - - BaseLib::TMP::foreach<EnabledElementTraits>( - [this]<typename ET>(ET*) - { - using MeshElement = typename ET::Element; - using ShapeFunction = typename ET::ShapeFunction; - using LowerOrderShapeFunction = - typename ET::LowerOrderShapeFunction; - - _builder[std::type_index(typeid(MeshElement))] = - makeLocalAssemblerBuilder<ShapeFunction, - LowerOrderShapeFunction>(); - }); - } - - /// Returns data pointer to the newly created local assembler data. - /// - /// \attention - /// The index \c id is not necessarily the mesh item's id. Especially when - /// having multiple meshes it will differ from the latter. - LADataIntfPtr operator()(std::size_t const id, - MeshLib::Element const& mesh_item, - ConstructorArgs&&... args) const - { - auto const type_idx = std::type_index(typeid(mesh_item)); - auto const it = _builder.find(type_idx); - - if (it != _builder.end()) - { - auto const num_local_dof = _dof_table.getNumberOfElementDOF(id); - return it->second(mesh_item, num_local_dof, - std::forward<ConstructorArgs>(args)...); - } - OGS_FATAL( - "You are trying to build a local assembler for an unknown mesh " - "element type ({:s})." - " Maybe you have disabled this mesh element type in your build " - "configuration, or a mesh element order does not match shape " - "function order given in the project file.", - type_idx.name()); - } - -private: - using LADataBuilder = - std::function<LADataIntfPtr(MeshLib::Element const& e, - std::size_t const local_matrix_size, - ConstructorArgs&&...)>; - - template <typename ShapeFunction> - using IntegrationMethod = typename NumLib::GaussLegendreIntegrationPolicy< - typename ShapeFunction::MeshElement>::IntegrationMethod; - - template <typename ShapeFunctionDisplacement, - typename ShapeFunctionPressure> - using LAData = - LocalAssemblerData<ShapeFunctionDisplacement, ShapeFunctionPressure, - IntegrationMethod<ShapeFunctionDisplacement>, - GlobalDim>; - - /// Generates a function that creates a new LocalAssembler of type - /// LAData<ShapeFunctionDisplacement, ShapeFunctionPressure>. Only functions - /// with shape function's dimension less or equal to the global dimension - /// are instantiated, e.g. following combinations of shape functions and - /// global dimensions: (Line2, 1), (Line2, 2), (Line2, 3), (Hex20, 3) but - /// not (Hex20, 2) or (Hex20, 1). - template <typename ShapeFunction, typename LowerOrderShapeFunction> - static LADataBuilder makeLocalAssemblerBuilder() - { - return [](MeshLib::Element const& e, - std::size_t const local_matrix_size, - ConstructorArgs&&... args) - { - return LADataIntfPtr{ - new LAData<ShapeFunction, LowerOrderShapeFunction>{ - e, local_matrix_size, - std::forward<ConstructorArgs>(args)...}}; - }; - } - - /// Mapping of element types to local assembler constructors. - std::unordered_map<std::type_index, LADataBuilder> _builder; - - NumLib::LocalToGlobalIndexMap const& _dof_table; -}; - -} // namespace ProcessLib::StokesFlow diff --git a/ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h b/ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h new file mode 100644 index 00000000000..6a819e69d4e --- /dev/null +++ b/ProcessLib/Utils/LocalAssemblerFactoryTaylorHoodForOrderGeN.h @@ -0,0 +1,171 @@ +/** + * \file + * \copyright + * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include "EnabledElements.h" +#include "GenericLocalDataInitializer.h" + +namespace ProcessLib +{ +template <typename ShapeFunction, + typename LowerOrderShapeFunction, + typename LocalAssemblerInterface, + template <typename /* shp fct */, + typename /* lower order shp fct */, + typename /* int meth */, + int /* global dim */> + class LocalAssemblerImplementation, + int GlobalDim, + typename... ConstructorArgs> +class LocalAssemblerBuilderFactoryTaylorHood +{ + using GLDI = GenericLocalDataInitializer<LocalAssemblerInterface, + ConstructorArgs...>; + using LocAsmIntfPtr = typename GLDI::LocAsmIntfPtr; + using LocAsmBuilder = typename GLDI::LocAsmBuilder; + + using IntegrationMethod = typename NumLib::GaussLegendreIntegrationPolicy< + typename ShapeFunction::MeshElement>::IntegrationMethod; + + using LocAsmImpl = LocalAssemblerImplementation<ShapeFunction, + LowerOrderShapeFunction, + IntegrationMethod, + GlobalDim>; + + LocalAssemblerBuilderFactoryTaylorHood() = delete; + +public: + /// Generates a function that creates a new local assembler of type + /// \c LocAsmImpl. + static LocAsmBuilder create() + { + return [](MeshLib::Element const& e, + std::size_t const local_matrix_size, + ConstructorArgs&&... args) + { + return std::make_unique<LocAsmImpl>( + e, local_matrix_size, std::forward<ConstructorArgs>(args)...); + }; + } +}; + +/** + * Local assembler factory for Taylor-Hood elements. + * + * Elements/shape functions must be of order greater than or equal to \c + * MinShapeFctOrder. + * + * If \c MinShapeFctOrder is 1, local assemblers are instantiated also for + * linear mesh elements. In this case we don't have Taylor-Hood elements for + * linear mesh elements. Instead, on linear mesh elements all shape functions + * will have the same order (namely 1). + */ +template <int MinShapeFctOrder, + typename LocalAssemblerInterface, + template <typename /* shp fct */, + typename /* lower order shp fct */, + typename /* int meth */, + int /* global dim */> + class LocalAssemblerImplementation, + int GlobalDim, + typename... ConstructorArgs> +class LocalAssemblerFactoryTaylorHoodForOrderGeN final + : public ProcessLib::GenericLocalDataInitializer<LocalAssemblerInterface, + ConstructorArgs...> +{ + using Base = + ProcessLib::GenericLocalDataInitializer<LocalAssemblerInterface, + ConstructorArgs...>; + + template <typename ShapeFunction, typename LowerOrderShapeFunction> + using LocAsmBuilderFactory = + LocalAssemblerBuilderFactoryTaylorHood<ShapeFunction, + LowerOrderShapeFunction, + LocalAssemblerInterface, + LocalAssemblerImplementation, + GlobalDim, + ConstructorArgs...>; + + struct IsElementEnabled + { + template <typename ElementTraits> + constexpr bool operator()(ElementTraits*) const + { + if constexpr (GlobalDim < ElementTraits::ShapeFunction::DIM) + { + return false; + } + + if constexpr (ElementTraits::Element::dimension < 2) + { + // in OGS Taylor-Hood elements are available in 2D and 3D only + return false; + } + + return ElementTraits::ShapeFunction::ORDER >= MinShapeFctOrder; + } + }; + +public: + explicit LocalAssemblerFactoryTaylorHoodForOrderGeN( + NumLib::LocalToGlobalIndexMap const& dof_table) + : Base(dof_table) + { + using EnabledElementTraits = + decltype(BaseLib::TMP::filter<EnabledElementTraitsLagrange>( + std::declval<IsElementEnabled>())); + + BaseLib::TMP::foreach<EnabledElementTraits>( + [this]<typename ET>(ET*) + { + using Elt = typename ET::Element; + using Shp = typename ET::ShapeFunction; + using ShpLow = typename ET::LowerOrderShapeFunction; + + Base::_builders[std::type_index(typeid(Elt))] = + LocalAssemblerBuilderFactoryTaylorHood< + Shp, + ShpLow, + LocalAssemblerInterface, + LocalAssemblerImplementation, + GlobalDim, + ConstructorArgs...>::create(); + }); + } +}; + +/// HM processes in OGS are defined for linear and higher order elements. +template <typename LocalAssemblerInterface, + template <typename, typename, typename, int> + class LocalAssemblerImplementation, + int GlobalDim, + typename... ConstructorArgs> +using LocalAssemblerFactoryHM = + LocalAssemblerFactoryTaylorHoodForOrderGeN<1, + LocalAssemblerInterface, + LocalAssemblerImplementation, + GlobalDim, + ConstructorArgs...>; + +/// Stokes flow in OGS is defined for higher order elements only. +template <typename LocalAssemblerInterface, + template <typename, typename, typename, int> + class LocalAssemblerImplementation, + int GlobalDim, + typename... ConstructorArgs> +using LocalAssemblerFactoryStokes = + LocalAssemblerFactoryTaylorHoodForOrderGeN<2, + LocalAssemblerInterface, + LocalAssemblerImplementation, + GlobalDim, + ConstructorArgs...>; + +} // namespace ProcessLib diff --git a/ProcessLib/Utils/LocalDataInitializerHM.h b/ProcessLib/Utils/LocalDataInitializerHM.h deleted file mode 100644 index ba4eb33b8f4..00000000000 --- a/ProcessLib/Utils/LocalDataInitializerHM.h +++ /dev/null @@ -1,151 +0,0 @@ -/** - * \file - * \copyright - * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org) - * Distributed under a Modified BSD License. - * See accompanying file LICENSE.txt or - * http://www.opengeosys.org/project/license - * - */ - -#pragma once - -#include <functional> -#include <memory> -#include <type_traits> -#include <typeindex> -#include <typeinfo> -#include <unordered_map> - -#include "EnabledElements.h" -#include "MeshLib/Elements/Elements.h" -#include "NumLib/DOF/LocalToGlobalIndexMap.h" -#include "NumLib/Fem/FiniteElement/LowerDimShapeTable.h" -#include "NumLib/Fem/Integration/GaussLegendreIntegrationPolicy.h" - -namespace ProcessLib -{ -/// The LocalDataInitializerHM is a functor creating a local assembler data with -/// corresponding to the mesh element type shape functions and calling -/// initialization of the new local assembler data. -/// For example for MeshLib::Quad a local assembler data with template argument -/// NumLib::ShapeQuad4 is created. -/// -/// \attention This is modified version of the ProcessLib::LocalDataInitializer -/// class which does not include line or point elements. For the shape functions -/// of order 2 (used for displacement) a shape function of order 1 will be used -/// for the scalar variables. -template <typename LocalAssemblerInterface, - template <typename, typename, typename, int> class LocalAssemblerData, - int GlobalDim, typename... ConstructorArgs> -class LocalDataInitializerHM final -{ - struct IsElementEnabled - { - template <typename ElementTraits> - constexpr bool operator()(ElementTraits*) const - { - if constexpr (GlobalDim < ElementTraits::ShapeFunction::DIM) - { - return false; - } - - // mechanics processes in OGS are defined in 2D and 3D only - return ElementTraits::Element::dimension >= 2; - } - }; - -public: - using LADataIntfPtr = std::unique_ptr<LocalAssemblerInterface>; - - explicit LocalDataInitializerHM( - NumLib::LocalToGlobalIndexMap const& dof_table) - : _dof_table(dof_table) - { - using EnabledElementTraits = - decltype(BaseLib::TMP::filter<EnabledElementTraitsLagrange>( - std::declval<IsElementEnabled>())); - - BaseLib::TMP::foreach<EnabledElementTraits>( - [this]<typename ET>(ET*) - { - using MeshElement = typename ET::Element; - using Shp = typename ET::ShapeFunction; - using ShpLow = typename ET::LowerOrderShapeFunction; - - _builder[std::type_index(typeid(MeshElement))] = - makeLocalAssemblerBuilder<Shp, ShpLow>(); - }); - } - - /// Returns data pointer to the newly created local assembler data. - /// - /// \attention - /// The index \c id is not necessarily the mesh item's id. Especially when - /// having multiple meshes it will differ from the latter. - LADataIntfPtr operator()(std::size_t const id, - MeshLib::Element const& mesh_item, - ConstructorArgs&&... args) const - { - auto const type_idx = std::type_index(typeid(mesh_item)); - auto const it = _builder.find(type_idx); - - if (it != _builder.end()) - { - auto const num_local_dof = _dof_table.getNumberOfElementDOF(id); - return it->second(mesh_item, num_local_dof, - std::forward<ConstructorArgs>(args)...); - } - OGS_FATAL( - "You are trying to build a local assembler for an unknown mesh " - "element type ({:s})." - " Maybe you have disabled this mesh element type in your build " - "configuration, or a mesh element order does not match shape " - "function order given in the project file.", - type_idx.name()); - } - -private: - using LADataBuilder = - std::function<LADataIntfPtr(MeshLib::Element const& e, - std::size_t const local_matrix_size, - ConstructorArgs&&...)>; - - template <typename ShapeFunction> - using IntegrationMethod = typename NumLib::GaussLegendreIntegrationPolicy< - typename ShapeFunction::MeshElement>::IntegrationMethod; - - template <typename ShapeFunctionDisplacement, - typename ShapeFunctionPressure> - using LAData = - LocalAssemblerData<ShapeFunctionDisplacement, ShapeFunctionPressure, - IntegrationMethod<ShapeFunctionDisplacement>, - GlobalDim>; - - /// Generates a function that creates a new LocalAssembler of type - /// LAData<ShapeFunctionDisplacement, ShapeFunctionPressure>. Only functions - /// with shape function's dimension less or equal to the global dimension - /// are instantiated, e.g. following combinations of shape functions and - /// global dimensions: (Line2, 1), (Line2, 2), (Line2, 3), (Hex20, 3) but - /// not (Hex20, 2) or (Hex20, 1). - template <typename ShapeFunction, typename LowerOrderShapeFunction> - static LADataBuilder makeLocalAssemblerBuilder() - { - return [](MeshLib::Element const& e, - std::size_t const local_matrix_size, - ConstructorArgs&&... args) - { - return LADataIntfPtr{ - new LAData<ShapeFunction, LowerOrderShapeFunction>{ - e, local_matrix_size, - std::forward<ConstructorArgs>(args)...}}; - }; - } - - /// Mapping of element types to local assembler constructors. - std::unordered_map<std::type_index, LADataBuilder> _builder; - - NumLib::LocalToGlobalIndexMap const& _dof_table; -}; - -} // namespace ProcessLib -- GitLab