-
Lisa Julia Nebel authoredLisa Julia Nebel authored
moebiusstrip.hh 3.75 KiB
#ifndef DUNE_GFE_MOEBIUSSTRIP_GRIDFUNCTION_HH
#define DUNE_GFE_MOEBIUSSTRIP_GRIDFUNCTION_HH
#include <cmath>
#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>
#include <dune/curvedgrid/gridfunctions/analyticgridfunction.hh>
namespace Dune {
/// \brief Functor representing a Möbius strip in 3D, where the base circle is the circle in the x-y-plane with radius_ around 0,0,0
template <class T = double>
class MoebiusStripProjection
{
static const int dim = 3;
using Domain = FieldVector<T,dim>;
using Jacobian = FieldMatrix<T,dim,dim>;
T radius_;
public:
MoebiusStripProjection (T radius)
: radius_(radius)
{}
/// \brief Project the coordinate to the MS using closest point projection
Domain operator() (const Domain& x) const
{
double nrm = std::sqrt(x[0]*x[0] + x[1]*x[1]);
//center for the point x - it lies on the circle around (0,0,0) with radius radius_ in the x-y-plane
Domain center{x[0] * radius_/nrm, x[1] * radius_/nrm, 0};
double cosu = x[0]/nrm;
double sinu = x[1]/nrm;
double cosuhalf = std::sqrt((1+cosu)/2);
cosuhalf *= (sinu < 0) ? (-1) : 1 ; // u goes from 0 to 2*pi, so cosuhalf is negative if sinu < 0, we multiply that here
double sinuhalf = std::sqrt((1-cosu)/2); //u goes from 0 to 2*pi, so sinuhalf is always >= 0
// now calculate line from center to the new point
// the direction is (cosuhalf*cosu,cosuhalf*sinu,sinuhalf), as can be seen from the formula to construct the MS, we normalize this vector
Domain centerToPointOnMS{cosuhalf*cosu,cosuhalf*sinu,sinuhalf};
centerToPointOnMS /= centerToPointOnMS.two_norm();
Domain centerToX = center - x;
// We need the length, let theta be the angle between the vector centerToX and center to centerToPointOnMS
// then cos(theta) = centerToX*centerToPointOnMS/(len(centerToX)*len(centerToPointOnMS))
// We want to project the point to MS, s.t. the angle between the MS and the projection is 90deg
// Then, length = cos(theta) * len(centerToX) = centerToX*centerToPointOnMS/len(centerToPointOnMS) = centerToX*centerToPointOnMS
double length = - centerToX * centerToPointOnMS;
centerToPointOnMS *= length;
return center + centerToPointOnMS;
}
/// \brief derivative of the projection to the MS
friend auto derivative (const MoebiusStripProjection& moebiusStrip)
{
DUNE_THROW(NotImplemented,"The derivative of the projection to the Möbius strip is not implemented yet!");
return [radius = moebiusStrip.radius_](const Domain& x)
{
Jacobian out;
return out;
};
}
/// \brief Normal Vector of the MS
Domain normal (const Domain& x) const
{
using std::sqrt;
Domain nVec = {x[0],x[1],0};
double nrm = std::sqrt(x[0]*x[0] + x[1]*x[1]);
double cosu = x[0]/nrm;
double sinu = x[1]/nrm;
double cosuhalf = std::sqrt((1+cosu)/2);
cosuhalf *= (sinu < 0) ? (-1) : 1 ; // u goes from 0 to 2*pi, so cosuhalf is negative if sinu < 0, we multiply that here
double sinuhalf = std::sqrt((1-cosu)/2);
nVec[2] = (-1)*cosuhalf*(cosu*x[0]+sinu*x[1])/sinuhalf;
nVec /= nVec.two_norm();
return nVec;
}
/// \brief The mean curvature of the MS
T mean_curvature (const Domain& /*x*/) const
{
DUNE_THROW(NotImplemented,"The mean curvature of the Möbius strip is not implemented yet!");
return 1;
}
/// \brief The area of the MS
T area () const
{
DUNE_THROW(NotImplemented,"The area of the Möbius strip is not implemented yet!");
return 1;
}
};
/// \brief construct a grid function representing the parametrization of a MS
template <class Grid, class T>
auto moebiusStripGridFunction (T radius)
{
return analyticGridFunction<Grid>(MoebiusStripProjection<T>{radius});
}
} // end namespace Dune
#endif // DUNE_GFE_MOEBIUSSTRIP_GRIDFUNCTION_HH