Newer
Older
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/gfe/assemblers/cosseratrodenergy.hh>
#include <dune/gfe/localgeodesicfefunction.hh>
#include <dune/gfe/spaces/productmanifold.hh>
#include <dune/gfe/spaces/realtuple.hh>
#include <dune/gfe/spaces/rotation.hh>
using namespace Dune::Indices;
// Type used for algebraic rod configurations
using TargetSpace = GFE::ProductManifold<RealTuple<double,3>,Rotation<double,3> >;
using SolutionType = std::vector<TargetSpace>;
// Problem settings
const int numRodBaseElements = 100;
// ///////////////////////////////////////
// Create the grid
// ///////////////////////////////////////
typedef OneDGrid GridType;
GridType grid(numRodBaseElements, 0, 1);
using GridView = GridType::LeafGridView;
GridView gridView = grid.leafGridView();
using FEBasis = Functions::LagrangeBasis<GridView,1>;
FEBasis feBasis(gridView);
SolutionType x(feBasis.size());
// //////////////////////////
// Initial solution
// //////////////////////////
for (size_t i=0; i<x.size(); i++)
{
double s = double(i)/(x.size()-1);
x[i][_0] = {0.1*std::cos(2*M_PI*s), 0.1*std::sin(2*M_PI*s), s};
x[i][_1] = Rotation<double,3>::identity();
//x[i].q = Quaternion<double>(zAxis, (double(i)*M_PI)/(2*(x.size()-1)) );
}
FieldVector<double,3> zAxis(0); zAxis[2]=1;
x.back()[_1] = Rotation<double,3>(zAxis, M_PI/4);
// /////////////////////////////////////////////////////////////////////
// Create a second, rotated copy of the configuration
// /////////////////////////////////////////////////////////////////////
FieldVector<double,3> displacement {0, 1, 0};
FieldVector<double,3> axis = {1,0,0};
Rotation<double,3> rotation(axis,M_PI/2);
SolutionType rotatedX = x;
for (size_t i=0; i<rotatedX.size(); i++)
{
rotatedX[i][_0] = rotation.rotate(x[i][_0].globalCoordinates());
rotatedX[i][_0].globalCoordinates() += displacement;
rotatedX[i][_1] = rotation.mult(x[i][_1]);
using GeodesicInterpolationRule = LocalGeodesicFEFunction<1, double,
FEBasis::LocalView::Tree::FiniteElement,
GFE::CosseratRodEnergy<FEBasis,
GeodesicInterpolationRule,
double> localRodEnergy(gridView,
1,1,1,1e6,0.3);
SolutionType referenceConfiguration(gridView.size(1));
for (const auto& vertex : vertices(gridView))
{
auto idx = gridView.indexSet().index(vertex);
referenceConfiguration[idx][_0] = {0.0, 0.0, vertex.geometry().corner(0)[0]};
referenceConfiguration[idx][_1] = Rotation<double,3>::identity();
localRodEnergy.setReferenceConfiguration(referenceConfiguration);
auto localView = feBasis.localView();
localView.bind(*gridView.begin<0>());
SolutionType localX = {x[0], x[1]};
SolutionType localRotatedX = {rotatedX[0], rotatedX[1]};
if (std::abs(localRodEnergy.energy(localView, localX) - localRodEnergy.energy(localView, localRotatedX)) > 1e-6)
DUNE_THROW(Dune::Exception, "Rod energy not invariant under rigid body motions!");
}
catch (Exception& e) {
std::cout << e.what() << std::endl;
}