Skip to content
Snippets Groups Projects
Commit 3aec4026 authored by Sander, Oliver's avatar Sander, Oliver
Browse files

Merge branch 'feature/cosserat-continuum-nonplanar' into 'master'

Cosserat-Continuum-Nonplanar

See merge request !72
parents 5e98bd03 2a48d052
No related branches found
No related tags found
1 merge request!72Cosserat-Continuum-Nonplanar
Pipeline #6313 passed
......@@ -8,4 +8,4 @@ Version: svn
Maintainer: oliver.sander@tu-dresden.de
#depending on
Depends: dune-common(>=2.7) dune-grid(>=2.7) dune-uggrid dune-istl dune-localfunctions dune-geometry (>=2.7) dune-functions (>=2.7) dune-solvers dune-fufem dune-elasticity (>=2.7)
Suggests: dune-foamgrid dune-parmg dune-vtk dune-curvedgeometry
Suggests: dune-foamgrid dune-parmg dune-vtk dune-curvedgrid
......@@ -109,6 +109,23 @@ class CosseratVTKWriter
}
public:
/** \brief Write a configuration given with respect to a scalar function space basis
*/
template <typename Basis>
static void write(const Basis& basis,
const Dune::TupleVector<std::vector<RealTuple<double,3> >,
std::vector<Rotation<double,3> > >& configuration,
const std::string& filename)
{
using namespace Dune::TypeTree::Indices;
std::vector<RigidBodyMotion<double,3>> xRBM(basis.size());
for (int i = 0; i < basis.size(); i++) {
for (int j = 0; j < 3; j ++) // Displacement part
xRBM[i].r[j] = configuration[_0][i][j];
xRBM[i].q = configuration[_1][i]; // Rotation part
}
write(basis,xRBM,filename);
}
/** \brief Write a configuration given with respect to a scalar function space basis
*/
......
#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
#ifndef DUNE_GFE_TWISTEDSTRIP_GRIDFUNCTION_HH
#define DUNE_GFE_TWISTEDSTRIP_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 twisted strip in 3D, with length length_ and nTwists twists
template <class T = double>
class TwistedStripProjection
{
static const int dim = 3;
using Domain = FieldVector<T,dim>;
using Jacobian = FieldMatrix<T,dim,dim>;
T length_;
double nTwists_;
public:
TwistedStripProjection (T length, double nTwists)
: length_(length),
nTwists_(nTwists)
{}
/// \brief Project the coordinate to the twisted strip using closest point projection
Domain operator() (const Domain& x) const
{
// Angle for the x - position of the point
double alpha = std::acos(-1)*nTwists_*x[0]/length_;
double cosalpha = std::cos(alpha);
double sinalpha = std::sin(alpha);
// Add the line from middle to the new point - the direction is (0,cosalpha,sinalpha)
// We need the distance, calculated by (y^2 + z^2)^0.5
double dist = std::sqrt(x[1]*x[1] + x[2]*x[2]);
double y = std::abs(cosalpha*dist);
if (x[1] < 0 and std::abs(x[1]) > std::abs(x[2])) { // only trust the sign of x[1] if it is larger than x[2]
y *= (-1);
} else if (std::abs(x[1]) <= std::abs(x[2])) {
if (cosalpha * sinalpha >= 0 and x[2] < 0) // if cosalpha*sinalpha > 0, x[1] and x[2] must have the same sign
y *= (-1);
if (cosalpha * sinalpha <= 0 and x[2] > 0) // if cosalpha*sinalpha < 0, x[1] and x[2] must have opposite signs
y *= (-1);
}
double z = std::abs(sinalpha*dist);
if (x[2] < 0 and std::abs(x[2]) > std::abs(x[1])) {
z *= (-1);
} else if (std::abs(x[2]) <= std::abs(x[1])) {
if (cosalpha * sinalpha >= 0 and x[1] < 0)
z *= (-1);
if (cosalpha * sinalpha <= 0 and x[1] > 0)
z *= (-1);
}
return {x[0], y , z};
}
/// \brief derivative of the projection to the twistedstrip
friend auto derivative (const TwistedStripProjection& twistedStrip)
{
DUNE_THROW(NotImplemented,"The derivative of the projection to the twisted strip is not implemented yet!");
return [length = twistedStrip.length_, nTwists = twistedStrip.nTwists_](const Domain& x)
{
Jacobian out;
return out;
};
}
/// \brief Normal Vector of the twisted strip
Domain normal (const Domain& x) const
{
// Angle for the x - position of the point
double alpha = std::acos(-1)*nTwists_*x[0]/length_;
std::cout << "normal at " << x[0] << "is " << -std::sin(alpha) << ", " << std::cos(alpha) << std::endl;
return {0,-std::sin(alpha), std::cos(alpha)};
}
/// \brief The mean curvature of the twisted strip
T mean_curvature (const Domain& /*x*/) const
{
DUNE_THROW(NotImplemented,"The mean curvature of the twisted strip is not implemented yet!");
return 1;
}
/// \brief The area of the twisted strip
T area (T width) const
{
return length_*width;
}
};
/// \brief construct a grid function representing the parametrization of a twisted strip
template <class Grid, class T>
auto twistedStripGridFunction (T length, double nTwists)
{
return analyticGridFunction<Grid>(TwistedStripProjection<T>{length, nTwists});
}
} // end namespace Dune
#endif // DUNE_GFE_TWISTEDSTRIP_GRIDFUNCTION_HH
......@@ -9,6 +9,8 @@
#include <dune/fufem/boundarypatch.hh>
#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
#include <dune/gfe/localenergy.hh>
#include <dune/gfe/localgeodesicfefunction.hh>
#include <dune/gfe/rigidbodymotion.hh>
......@@ -21,7 +23,15 @@
#include <dune/localfunctions/lagrange/lfecache.hh>
#endif
template<class Basis, int dim, class field_type=double>
/** \brief Assembles the cosserat energy for a single element.
*
* \tparam Basis Type of the Basis used for assembling
* \tparam dim Dimension of the Targetspace, 3
* \tparam field_type The coordinate type of the TargetSpace
* \tparam StressFreeStateGridFunction Type of the GridFunction representing the Cosserat shell in a stress free state
*/
template<class Basis, int dim, class field_type=double, class StressFreeStateGridFunction =
Dune::Functions::DiscreteGlobalBasisFunction<Basis,std::vector<Dune::FieldVector<double, Basis::GridView::dimensionworld>> > >
class NonplanarCosseratShellEnergy
: public Dune::GFE::LocalEnergy<Basis,RigidBodyMotion<field_type,dim> >
{
......@@ -40,13 +50,16 @@ class NonplanarCosseratShellEnergy
public:
/** \brief Constructor with a set of material parameters
* \param parameters The material parameters
* \param parameters The material parameters
* \param stressFreeStateGridFunction Pointer to a parametrization representing the Cosserat shell in a stress-free state
*/
NonplanarCosseratShellEnergy(const Dune::ParameterTree& parameters,
const StressFreeStateGridFunction* stressFreeStateGridFunction,
const BoundaryPatch<GridView>* neumannBoundary,
const std::function<Dune::FieldVector<double,3>(Dune::FieldVector<double,dimworld>)> neumannFunction,
const std::function<Dune::FieldVector<double,3>(Dune::FieldVector<double,dimworld>)> volumeLoad)
: neumannBoundary_(neumannBoundary),
: stressFreeStateGridFunction_(stressFreeStateGridFunction),
neumannBoundary_(neumannBoundary),
neumannFunction_(neumannFunction),
volumeLoad_(volumeLoad)
{
......@@ -111,6 +124,9 @@ public:
/** \brief Curvature parameters */
double b1_, b2_, b3_;
/** \brief The geometry used for assembling */
const StressFreeStateGridFunction* stressFreeStateGridFunction_;
/** \brief The Neumann boundary */
const BoundaryPatch<GridView>* neumannBoundary_;
......@@ -121,15 +137,34 @@ public:
const std::function<Dune::FieldVector<double,3>(Dune::FieldVector<double,dimworld>)> volumeLoad_;
};
template <class Basis, int dim, class field_type>
typename NonplanarCosseratShellEnergy<Basis,dim,field_type>::RT
NonplanarCosseratShellEnergy<Basis,dim,field_type>::
template <class Basis, int dim, class field_type, class StressFreeStateGridFunction>
typename NonplanarCosseratShellEnergy<Basis, dim, field_type, StressFreeStateGridFunction>::RT
NonplanarCosseratShellEnergy<Basis,dim,field_type, StressFreeStateGridFunction>::
energy(const typename Basis::LocalView& localView,
const std::vector<RigidBodyMotion<field_type,dim> >& localSolution) const
{
// The element geometry
auto element = localView.element();
#if HAVE_DUNE_CURVEDGEOMETRY
// Construct a curved geometry of this element of the Cosserat shell in stress-free state
// When using element.geometry(), then the curvatures on the element are zero, when using a curved geometry, they are not
// If a parametrization representing the Cosserat shell in a stress-free state is given,
// this is used for the curved geometry approximation.
// The variable local holds the local coordinates in the reference element
// and localGeometry.global maps them to the world coordinates
Dune::CurvedGeometry<DT, gridDim, dimworld, Dune::CurvedGeometryTraits<DT, Dune::LagrangeLFECache<DT,DT,gridDim>>> geometry(referenceElement(element),
[this,element](const auto& local) {
if (not stressFreeStateGridFunction_) {
return element.geometry().global(local);
}
auto localGridFunction = localFunction(*stressFreeStateGridFunction_);
localGridFunction.bind(element);
return localGridFunction(local);
}, 2); /*order*/
#else
auto geometry = element.geometry();
#endif
// The set of shape functions on this element
const auto& localFiniteElement = localView.tree().finiteElement();
......@@ -215,17 +250,8 @@ energy(const typename Basis::LocalView& localView,
c += aScalar * eps[alpha][beta] * Dune::GFE::dyadicProduct(aContravariant[alpha], aContravariant[beta]);
#if HAVE_DUNE_CURVEDGEOMETRY
// Construct a curved geometry to evaluate the derivative of the normal field on each quadrature point
// The variable local holds the local coordinates in the reference element
// and localGeometry.global maps them to the world coordinates
// we want to take the derivative of the normal field on the element in world coordinates
Dune::CurvedGeometry<DT, gridDim, dimworld, Dune::CurvedGeometryTraits<DT, Dune::LagrangeLFECache<DT,DT,gridDim>>> curvedGeometry(referenceElement(element),
[localGeometry=element.geometry()](const auto& local) {
return localGeometry.global(local);
}, 1); //order = 1
// Second fundamental form: The derivative of the normal field
auto normalDerivative = curvedGeometry.normalGradient(quad[pt].position());
// Second fundamental form: The derivative of the normal field, on each quadrature point
auto normalDerivative = geometry.normalGradient(quad[pt].position());
#else
//In case dune-curvedgeometry is not installed, the normal derivative is set to zero.
Dune::FieldMatrix<double,3,3> normalDerivative(0);
......
......@@ -67,7 +67,7 @@ setup(const GridType& grid,
// //////////////////////////////////////////////////////////////////////////////////////
typedef DuneFunctionsBasis<Basis> FufemBasis;
FufemBasis basis(assembler_->basis_);
FufemBasis basis(assembler_->getBasis());
OperatorAssembler<FufemBasis,FufemBasis> operatorAssembler(basis, basis);
LaplaceAssembler<GridType, typename FufemBasis::LocalFiniteElement, typename FufemBasis::LocalFiniteElement> laplaceStiffness;
......
......@@ -24,7 +24,7 @@ numHomotopySteps = 1
tolerance = 1e-3
# Max number of steps of the trust region solver
maxTrustRegionSteps = 200
maxSolverSteps = 200
trustRegionScaling = 1 1 1 0.01 0.01 0.01
......
......@@ -20,7 +20,7 @@ numHomotopySteps = 1
tolerance = 1e-8
# Max number of steps of the trust region solver
maxTrustRegionSteps = 1000
maxSolverSteps = 1000
trustRegionScaling = 1 1 1 0.01 0.01 0.01
......
......@@ -59,7 +59,7 @@ initialDeformation = "x"
#############################################
# Inner solver, cholmod or multigrid
solvertype = multigrid
solvertype = trustRegion
# Number of homotopy steps for the Dirichlet boundary conditions
numHomotopySteps = 1
......
This diff is collapsed.
......@@ -554,7 +554,7 @@ int main (int argc, char *argv[]) try
// Create the chosen solver and solve!
///////////////////////////////////////////////////
if (parameterSet.get<std::string>("solvertype") == "multigrid") {
if (parameterSet.get<std::string>("solvertype", "trustRegion") == "trustRegion") {
#if MIXED_SPACE
MixedRiemannianTrustRegionSolver<GridType, CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>> solver;
solver.setup(*grid,
......@@ -603,7 +603,7 @@ int main (int argc, char *argv[]) try
x[_1][i] = xRBM[i].q;
}
#endif
} else { //parameterSet.get<std::string>("solvertype") == "cholmod"
} else { //parameterSet.get<std::string>("solvertype") == "proximalNewton"
#if MIXED_SPACE
DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
......
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