Skip to content
Snippets Groups Projects
Commit 5d742221 authored by Lisa Julia Nebel's avatar Lisa Julia Nebel
Browse files

Add localintegralenergy.hh and neumannenergy.hh, they assemble the energy for...

Add localintegralenergy.hh and neumannenergy.hh, they assemble the energy for a single element and work with a CompositeBasis

These classes work similarly to Dune::Elasticity::LocalIntegralEnergy and Dune::Elasticity::NeumannEnergy,
where the ones in Dune::Elasticity with a power basis (for the displacement function) and
Dune::GFE::LocalIntegralEnergy / Dune::GFE::NeumannEnergy work with a CompositeBasis (for the displacement AND the rotation),
so the indices to access the different parts of the basis are different.
parent fc0d3f87
No related branches found
No related tags found
1 merge request!48Migrate from dune-fufem to dune-functions bases
#ifndef DUNE_GFE_LOCALINTEGRALENERGY_HH
#define DUNE_GFE_LOCALINTEGRALENERGY_HH
#include <dune/common/fmatrix.hh>
#include <dune/common/fmatrixev.hh>
#include <dune/geometry/quadraturerules.hh>
#include <dune/gfe/localenergy.hh>
#include <dune/gfe/realtuple.hh>
#include <dune/gfe/rigidbodymotion.hh>
#include <dune/elasticity/materials/localdensity.hh>
namespace Dune::GFE {
/**
\brief Assembles the elastic energy for a single element integrating the localdensity over one element.
This class works similarly to the class Dune::Elasticity::LocalIntegralEnergy, where Dune::Elasticity::LocalIntegralEnergy extends
Dune::Elasticity::LocalEnergy and Dune::GFE::LocalIntegralEnergy extends Dune::GFE::LocalEnergy.
*/
template<class Basis, class... TargetSpaces>
class LocalIntegralEnergy
: public Dune::GFE::LocalEnergy<Basis,TargetSpaces...>
{
using LocalView = typename Basis::LocalView;
using GridView = typename LocalView::GridView;
using DT = typename GridView::Grid::ctype;
using RT = typename Dune::GFE::LocalEnergy<Basis,TargetSpaces...>::RT;
enum {gridDim=GridView::dimension};
public:
/** \brief Constructor with a local energy density
*/
LocalIntegralEnergy(const std::shared_ptr<Dune::Elasticity::LocalDensity<gridDim,RT,DT>>& ld)
: localDensity_(ld)
{}
/** \brief Assemble the energy for a single element */
RT energy(const typename Basis::LocalView& localView,
const std::vector<TargetSpaces>&... localSolutions) const
{
static_assert(sizeof...(TargetSpaces) > 0, "LocalIntegralEnergy needs at least one TargetSpace!");
using TargetSpace = typename std::tuple_element<0, std::tuple<TargetSpaces...> >::type;
static_assert( (std::is_same<TargetSpace, RigidBodyMotion<RT,gridDim>>::value)
or (std::is_same<TargetSpace, RealTuple<RT,gridDim>>::value), "The first TargetSpace of LocalIntegralEnergy needs to be RigidBodyMotion or RealTuple!" );
const std::vector<TargetSpace>& localSolution = std::get<0>(std::forward_as_tuple(localSolutions...));
using namespace Dune::Indices;
// powerBasis: grab the finite element of the first child
const auto& localFiniteElement = localView.tree().child(_0,0).finiteElement();
const auto& element = localView.element();
RT energy = 0;
// store gradients of shape functions and base functions
std::vector<FieldMatrix<DT,1,gridDim> > referenceGradients(localFiniteElement.size());
std::vector<FieldVector<DT,gridDim> > gradients(localFiniteElement.size());
int quadOrder = (element.type().isSimplex()) ? localFiniteElement.localBasis().order()
: localFiniteElement.localBasis().order() * gridDim;
const auto& quad = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
for (const auto& qp : quad)
{
const DT integrationElement = element.geometry().integrationElement(qp.position());
const auto jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(qp.position());
// Global position
auto x = element.geometry().global(qp.position());
// Get gradients of shape functions
localFiniteElement.localBasis().evaluateJacobian(qp.position(), referenceGradients);
// compute gradients of base functions
for (size_t i=0; i<gradients.size(); ++i)
jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
// Deformation gradient
FieldMatrix<RT,gridDim,gridDim> deformationGradient(0);
for (size_t i=0; i<gradients.size(); i++)
for (int j=0; j<gridDim; j++)
deformationGradient[j].axpy(localSolution[i][j], gradients[i]);
// Integrate the energy density
energy += qp.weight() * integrationElement * (*localDensity_)(x, deformationGradient);
}
return energy;
}
protected:
const std::shared_ptr<Dune::Elasticity::LocalDensity<gridDim,RT,DT>> localDensity_ = nullptr;
};
} // namespace Dune::GFE
#endif //#ifndef DUNE_GFE_LOCALINTEGRALENERGY_HH
#ifndef DUNE_GFE_NEUMANNENERGY_HH
#define DUNE_GFE_NEUMANNENERGY_HH
#include <dune/geometry/quadraturerules.hh>
#include <dune/fufem/functions/virtualgridfunction.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/elasticity/assemblers/localenergy.hh>
namespace Dune::GFE {
/**
\brief Assembles the Neumann energy for a single element on the Neumann Boundary using the Neumann Function.
This class works similarly to the class Dune::Elasticity::NeumannEnergy, where Dune::Elasticity::NeumannEnergy extends
Dune::Elasticity::LocalEnergy and Dune::GFE::NeumannEnergy extends Dune::GFE::LocalEnergy.
*/
template<class Basis, class... TargetSpaces>
class NeumannEnergy
: public Dune::GFE::LocalEnergy<Basis,TargetSpaces...>
{
using LocalView = typename Basis::LocalView;
using GridView = typename LocalView::GridView;
using DT = typename GridView::Grid::ctype;
using RT = typename Dune::GFE::LocalEnergy<Basis,TargetSpaces...>::RT;
enum {dim=GridView::dimension};
public:
/** \brief Constructor with a set of material parameters
* \param parameters The material parameters
*/
NeumannEnergy(const std::shared_ptr<BoundaryPatch<GridView>>& neumannBoundary,
std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<DT,dim>)> neumannFunction)
: neumannBoundary_(neumannBoundary),
neumannFunction_(neumannFunction)
{}
/** \brief Assemble the energy for a single element */
RT energy(const typename Basis::LocalView& localView,
const std::vector<TargetSpaces>&... localSolutions) const
{
static_assert(sizeof...(TargetSpaces) > 0, "NeumannEnergy needs at least one TargetSpace!");
using namespace Dune::Indices;
using TargetSpace = typename std::tuple_element<0, std::tuple<TargetSpaces...> >::type;
const std::vector<TargetSpace>& localSolution = std::get<0>(std::forward_as_tuple(localSolutions...));
const auto& localFiniteElement = localView.tree().child(_0,0).finiteElement();
const auto& element = localView.element();
RT energy = 0;
for (auto&& intersection : intersections(neumannBoundary_->gridView(), element)) {
if (not neumannBoundary_ or not neumannBoundary_->contains(intersection))
continue;
int quadOrder = localFiniteElement.localBasis().order();
const auto& quad = Dune::QuadratureRules<DT, dim-1>::rule(intersection.type(), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {
// Local position of the quadrature point
const Dune::FieldVector<DT,dim>& quadPos = intersection.geometryInInside().global(quad[pt].position());
const auto integrationElement = intersection.geometry().integrationElement(quad[pt].position());
// The value of the local function
std::vector<Dune::FieldVector<DT,1> > shapeFunctionValues;
localFiniteElement.localBasis().evaluateFunction(quadPos, shapeFunctionValues);
Dune::FieldVector<RT,dim> value(0);
for (size_t i=0; i<localFiniteElement.size(); i++)
for (int j=0; j<dim; j++)
value[j] += shapeFunctionValues[i] * localSolution[i][j];
// Value of the Neumann data at the current position
auto neumannValue = neumannFunction_( intersection.geometry().global(quad[pt].position()) );
// Only translational dofs are affected by the Neumann force
for (size_t i=0; i<neumannValue.size(); i++)
energy += (neumannValue[i] * value[i]) * quad[pt].weight() * integrationElement;
}
}
return energy;
}
private:
/** \brief The Neumann boundary */
const std::shared_ptr<BoundaryPatch<GridView>> neumannBoundary_;
/** \brief The function implementing the Neumann data */
std::function<Dune::FieldVector<double,dim>(Dune::FieldVector<DT,dim>)> neumannFunction_;
};
} // namespace Dune::GFE
#endif //#ifndef DUNE_GFE_NEUMANNENERGY_HH
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment