Newer
Older

Sander, Oliver
committed
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_GFE_PERIODIC_1D_PQ1NODALBASIS_HH
#define DUNE_GFE_PERIODIC_1D_PQ1NODALBASIS_HH
#include <dune/common/exceptions.hh>

Sander, Oliver
committed
#include <dune/localfunctions/lagrange/pqkfactory.hh>
#include <dune/functions/functionspacebases/nodes.hh>
#include <dune/functions/functionspacebases/flatmultiindex.hh>
#include <dune/functions/functionspacebases/defaultglobalbasis.hh>

Sander, Oliver
committed
namespace Dune {
namespace Functions {
// *****************************************************************************
// This is the reusable part of the basis. It contains
//
// PQ1PreBasis

Sander, Oliver
committed
// PQ1NodeIndexSet
// PQ1Node
//
// The pre-basis allows to create the others and is the owner of possible shared

Sander, Oliver
committed
// state. These three components do _not_ depend on the global basis or index
// set and can be used without a global basis.
// *****************************************************************************
template<typename GV>

Sander, Oliver
committed
class Periodic1DPQ1Node;
template<typename GV, class MI>

Sander, Oliver
committed
class Periodic1DPQ1NodeIndexSet;
template<typename GV, class MI>
class Periodic1DPQ1PreBasis

Sander, Oliver
committed
{
static const int dim = GV::dimension;
public:
//! The grid view that the FE basis is defined on

Sander, Oliver
committed
using GridView = GV;
//! Type used for indices and size information
using size_type = std::size_t;

Sander, Oliver
committed
using Node = Periodic1DPQ1Node<GV>;
using IndexSet = Periodic1DPQ1NodeIndexSet<GV, MI>;

Sander, Oliver
committed
/** \brief Type used for global numbering of the basis vectors */
using MultiIndex = MI;
//! Type used for prefixes handed to the size() method
using SizePrefix = Dune::ReservedVector<size_type, 1>;

Sander, Oliver
committed
//! Constructor for a given grid view object
Periodic1DPQ1PreBasis(const GridView& gv) :

Sander, Oliver
committed
gridView_(gv)
{}
void initializeIndices()
{}
/** \brief Obtain the grid view that the basis is defined on
*/
const GridView& gridView() const
{
return gridView_;
}
//! Update the stored grid view, to be called if the grid has changed
void update (const GridView& gv)
{
gridView_ = gv;
}
Node makeNode() const

Sander, Oliver
committed
{
return Node{};

Sander, Oliver
committed
}
IndexSet makeIndexSet() const

Sander, Oliver
committed
{
return IndexSet{*this};

Sander, Oliver
committed
}
size_type size() const
{
return gridView_.size(dim)-1;
}
//! Return number possible values for next position in multi index
size_type size(const SizePrefix prefix) const
{
if (prefix.size() == 0)
return size();
if (prefix.size() == 1)
return 0;
DUNE_THROW(RangeError, "Method size() can only be called for prefixes of length up to one");
}
//! Get the total dimension of the space spanned by this basis

Sander, Oliver
committed
size_type dimension() const
{
return size()-1;
}
size_type maxNodeSize() const
{

Sander, Oliver
committed
}
//protected:
const GridView gridView_;
};
template<typename GV>

Sander, Oliver
committed
class Periodic1DPQ1Node :
public LeafBasisNode

Sander, Oliver
committed
{
static const int dim = GV::dimension;
static const int maxSize = Dune::power(2,GV::dimension);

Sander, Oliver
committed
using FiniteElementCache = typename Dune::PQkLocalFiniteElementCache<typename GV::ctype, double, dim, 1>;
public:
using size_type = std::size_t;

Sander, Oliver
committed
using Element = typename GV::template Codim<0>::Entity;
using FiniteElement = typename FiniteElementCache::FiniteElementType;
Periodic1DPQ1Node() :

Sander, Oliver
committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
finiteElement_(nullptr),
element_(nullptr)
{}
//! Return current element, throw if unbound
const Element& element() const
{
return *element_;
}
/** \brief Return the LocalFiniteElement for the element we are bound to
*
* The LocalFiniteElement implements the corresponding interfaces of the dune-localfunctions module
*/
const FiniteElement& finiteElement() const
{
return *finiteElement_;
}
//! Bind to element.
void bind(const Element& e)
{
element_ = &e;
finiteElement_ = &(cache_.get(element_->type()));
this->setSize(finiteElement_->size());
}
protected:
FiniteElementCache cache_;
const FiniteElement* finiteElement_;
const Element* element_;
};
template<typename GV, class MI>

Sander, Oliver
committed
class Periodic1DPQ1NodeIndexSet
{
constexpr static int dim = GV::dimension;

Sander, Oliver
committed
public:
using size_type = std::size_t;

Sander, Oliver
committed
/** \brief Type used for global numbering of the basis vectors */
using MultiIndex = MI;
using PreBasis = Periodic1DPQ1PreBasis<GV, MI>;
using Node = Periodic1DPQ1Node<GV>;

Sander, Oliver
committed
Periodic1DPQ1NodeIndexSet(const PreBasis& preBasis) :
preBasis_(&preBasis),
node_(nullptr)

Sander, Oliver
committed
{}
/** \brief Bind the view to a grid element
*
* Having to bind the view to an element before being able to actually access any of its data members
* offers to centralize some expensive setup code in the 'bind' method, which can save a lot of run-time.
*/
void bind(const Node& node)
{
node_ = &node;
}
/** \brief Unbind the view
*/
void unbind()
{
node_ = nullptr;
}
/** \brief Size of subtree rooted in this node (element-local)
*/
size_type size() const
{
assert(node_ != nullptr);

Sander, Oliver
committed
return node_->finiteElement().size();
}
//! Maps from subtree index set [0..size-1] to a globally unique multi index in global basis
MultiIndex index(size_type i) const
{
Dune::LocalKey localKey = node_->finiteElement().localCoefficients().localKey(i);
const auto& gridIndexSet = preBasis_->gridView().indexSet();

Sander, Oliver
committed
const auto& element = node_->element();
//return {{ gridIndexSet.subIndex(element,localKey.subEntity(),dim) }};
MultiIndex idx{{gridIndexSet.subIndex(element,localKey.subEntity(),dim) }};
// make periodic
if (idx == gridIndexSet.size(dim)-1)
idx = {{0}};
return idx;
}
protected:
const PreBasis* preBasis_;

Sander, Oliver
committed
const Node* node_;
};
/** \brief Nodal basis of a scalar first-order Lagrangian finite element space
* on a one-dimensional domain with periodic boundary conditions

Sander, Oliver
committed
*
* \tparam GV The GridView that the space is defined on
*/
template<typename GV>
using Periodic1DPQ1NodalBasis = DefaultGlobalBasis<Periodic1DPQ1PreBasis<GV, FlatMultiIndex<std::size_t> > >;

Sander, Oliver
committed
} // end namespace Functions
} // end namespace Dune
#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_PQ1NODALBASIS_HH