Skip to content
Snippets Groups Projects
Commit b18fce9a authored by Patrick Jaap's avatar Patrick Jaap
Browse files

DuneFunctionsOperatorAssembler: use one localView twice if bases are the same

For operators with equal ansatz and trial space we can use one localView twice
instead of calling the expensive bind() twice.
parent a8d5cb9d
No related branches found
No related tags found
1 merge request!80DuneFunctionsOperatorAssembler: use one localView twice if bases are the same
Pipeline #30508 passed
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#ifndef DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH #ifndef DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH
#define DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH #define DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH
#include <type_traits>
#include <dune/istl/matrix.hh> #include <dune/istl/matrix.hh>
#include <dune/istl/matrixindexset.hh> #include <dune/istl/matrixindexset.hh>
...@@ -37,15 +39,15 @@ public: ...@@ -37,15 +39,15 @@ public:
{ {
patternBuilder.resize(trialBasis_, ansatzBasis_); patternBuilder.resize(trialBasis_, ansatzBasis_);
auto trialLocalView = trialBasis_.localView(); // create two localViews but use only one if bases are the same
auto ansatzLocalView = ansatzBasis_.localView();
auto ansatzLocalView = ansatzBasis_.localView(); auto seperateTrialLocalView = trialBasis_.localView();
auto& trialLocalView = selectTrialLocalView(ansatzLocalView, seperateTrialLocalView);
for (const auto& element : elements(trialBasis_.gridView())) for (const auto& element : elements(trialBasis_.gridView()))
{ {
trialLocalView.bind(element); // bind the localViews to the element
bind(ansatzLocalView, trialLocalView, element);
ansatzLocalView.bind(element);
// Add element stiffness matrix onto the global stiffness matrix // Add element stiffness matrix onto the global stiffness matrix
for (size_t i=0; i<trialLocalView.size(); ++i) for (size_t i=0; i<trialLocalView.size(); ++i)
...@@ -119,9 +121,10 @@ public: ...@@ -119,9 +121,10 @@ public:
template <class MatrixBackend, class LocalAssembler> template <class MatrixBackend, class LocalAssembler>
void assembleBulkEntries(MatrixBackend&& matrixBackend, LocalAssembler&& localAssembler) const void assembleBulkEntries(MatrixBackend&& matrixBackend, LocalAssembler&& localAssembler) const
{ {
auto trialLocalView = trialBasis_.localView(); // create two localViews but use only one if bases are the same
auto ansatzLocalView = ansatzBasis_.localView();
auto ansatzLocalView = ansatzBasis_.localView(); auto seperateTrialLocalView = trialBasis_.localView();
auto& trialLocalView = selectTrialLocalView(ansatzLocalView, seperateTrialLocalView);
using Field = std::decay_t<decltype(matrixBackend(trialLocalView.index(0), ansatzLocalView.index(0)))>; using Field = std::decay_t<decltype(matrixBackend(trialLocalView.index(0), ansatzLocalView.index(0)))>;
using LocalMatrix = Dune::Matrix<Dune::FieldMatrix<Field,1,1>>; using LocalMatrix = Dune::Matrix<Dune::FieldMatrix<Field,1,1>>;
...@@ -130,12 +133,10 @@ public: ...@@ -130,12 +133,10 @@ public:
for (const auto& element : elements(trialBasis_.gridView())) for (const auto& element : elements(trialBasis_.gridView()))
{ {
trialLocalView.bind(element); // bind the localViews to the element
bind(ansatzLocalView, trialLocalView, element);
ansatzLocalView.bind(element);
localMatrix.setSize(trialLocalView.size(), ansatzLocalView.size()); localMatrix.setSize(trialLocalView.size(), ansatzLocalView.size());
localAssembler(element, localMatrix, trialLocalView, ansatzLocalView); localAssembler(element, localMatrix, trialLocalView, ansatzLocalView);
// Add element stiffness matrix onto the global stiffness matrix // Add element stiffness matrix onto the global stiffness matrix
...@@ -270,6 +271,30 @@ public: ...@@ -270,6 +271,30 @@ public:
assembleBulkEntries(matrixBackend, std::forward<LocalAssembler>(localAssembler)); assembleBulkEntries(matrixBackend, std::forward<LocalAssembler>(localAssembler));
} }
private:
//! helper function to select a trialLocalView (possibly a reference to ansatzLocalView if bases are the same)
template<class AnsatzLocalView, class TrialLocalView>
TrialLocalView& selectTrialLocalView(AnsatzLocalView& ansatzLocalView, TrialLocalView& trialLocalView) const
{
if constexpr (std::is_same<TrialBasis,AnsatzBasis>::value)
if (&trialBasis_ == &ansatzBasis_)
return ansatzLocalView;
return trialLocalView;
}
//! small helper that checks whether two localViews are the same and binds one or both to an element
template<class AnsatzLocalView, class TrialLocalView, class E>
void bind(AnsatzLocalView& ansatzLocalView, TrialLocalView& trialLocalView, const E& e) const
{
ansatzLocalView.bind(e);
if constexpr (std::is_same<TrialBasis,AnsatzBasis>::value)
if (&trialLocalView == &ansatzLocalView)
return;
// localViews differ: bind trialLocalView too
trialLocalView.bind(e);
}
protected: protected:
const TrialBasis& trialBasis_; const TrialBasis& trialBasis_;
const AnsatzBasis& ansatzBasis_; const AnsatzBasis& ansatzBasis_;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment