From ae8e6bc3a6c73f78370f2340d68a6e528482beb7 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Wed, 14 Jan 2015 15:17:53 +0000 Subject: [PATCH] Energy functional for a certain type of chiral skyrmions Described in: Christof Melcher, "Chiral skyrmions in the plane", Proc. of the Royal Society, online DOI DOI: 10.1098/rspa.2014.0394 [[Imported from SVN: r9996]] --- dune/gfe/chiralskyrmionenergy.hh | 124 +++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 dune/gfe/chiralskyrmionenergy.hh diff --git a/dune/gfe/chiralskyrmionenergy.hh b/dune/gfe/chiralskyrmionenergy.hh new file mode 100644 index 00000000..55cc3201 --- /dev/null +++ b/dune/gfe/chiralskyrmionenergy.hh @@ -0,0 +1,124 @@ +#ifndef DUNE_GFE_CHIRALSKYRMIONENERGY_HH +#define DUNE_GFE_CHIRALSKYRMIONENERGY_HH + +#include <dune/common/fmatrix.hh> +#include <dune/geometry/quadraturerules.hh> + +#include <dune/gfe/localgeodesicfestiffness.hh> +#include <dune/gfe/localgeodesicfefunction.hh> + +namespace Dune { + +namespace GFE { + +/** \brief Energy of certain chiral Skyrmion + * + * The energy is discussed in: + * - Christof Melcher, "Chiral skyrmions in the plane", Proc. of the Royal Society, online DOI DOI: 10.1098/rspa.2014.0394 + */ +template<class GridView, class LocalFiniteElement, class field_type> +class ChiralSkyrmionEnergy +: public LocalGeodesicFEStiffness<GridView,LocalFiniteElement,UnitVector<field_type,3> > +{ + // various useful types + typedef UnitVector<field_type,3> TargetSpace; + typedef typename GridView::Grid::ctype DT; + typedef typename TargetSpace::ctype RT; + typedef typename GridView::template Codim<0>::Entity Entity; + + // some other sizes + enum {gridDim=GridView::dimension}; + +public: + + //! Dimension of a tangent space + enum { blocksize = TargetSpace::TangentVector::dimension }; + + /** \brief Assemble the energy for a single element */ + RT energy (const Entity& e, + const LocalFiniteElement& localFiniteElement, + const std::vector<TargetSpace>& localConfiguration) const; + + field_type h_ = 3; + field_type kappa_ = 1; +}; + +template <class GridView, class LocalFiniteElement, class field_type> +typename ChiralSkyrmionEnergy<GridView, LocalFiniteElement, field_type>::RT +ChiralSkyrmionEnergy<GridView, LocalFiniteElement, field_type>:: +energy(const Entity& element, + const LocalFiniteElement& localFiniteElement, + const std::vector<TargetSpace>& localConfiguration) const +{ + assert(element.type() == localFiniteElement.type()); + typedef typename GridView::template Codim<0>::Entity::Geometry Geometry; + + RT energy = 0; + typedef LocalGeodesicFEFunction<gridDim, double, LocalFiniteElement, TargetSpace> LocalGFEFunctionType; + LocalGFEFunctionType localGeodesicFEFunction(localFiniteElement,localConfiguration); + + int quadOrder = (element.type().isSimplex()) ? (localFiniteElement.localBasis().order()-1) * 2 + : localFiniteElement.localBasis().order() * 2 * gridDim; + + + + const Dune::QuadratureRule<double, gridDim>& quad + = Dune::QuadratureRules<double, gridDim>::rule(element.type(), quadOrder); + + for (size_t pt=0; pt<quad.size(); pt++) { + + // Local position of the quadrature point + const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position(); + + const double integrationElement = element.geometry().integrationElement(quadPos); + + const typename Geometry::JacobianInverseTransposed& jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos); + + double weight = quad[pt].weight() * integrationElement; + + // The value of the function + auto value = localGeodesicFEFunction.evaluate(quadPos); + + // The derivative of the local function defined on the reference element + typename LocalGFEFunctionType::DerivativeType referenceDerivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value); + + // The derivative of the function defined on the actual element + typename LocalGFEFunctionType::DerivativeType derivative(0); + + for (size_t comp=0; comp<referenceDerivative.N(); comp++) + jacobianInverseTransposed.umv(referenceDerivative[comp], derivative[comp]); + + ////////////////////////////////////////////////////////////// + // Exchange energy (aka harmonic energy) + ////////////////////////////////////////////////////////////// + // The Frobenius norm is the correct norm here if the metric of TargetSpace is the identity. + // (And if the metric of the domain space is the identity, which it always is here.) + energy += weight * 0.5 * derivative.frobenius_norm2(); + + ////////////////////////////////////////////////////////////// + // Dzyaloshinkii-Moriya interaction term + ////////////////////////////////////////////////////////////// + + // derivative[a][b] contains the partial derivative of m_a in the direction x_b + Dune::FieldVector<field_type, 3> curl = {derivative[2][1], -derivative[2][0], derivative[1][0]-derivative[0][1]}; + + FieldVector<field_type, 3> v = value.globalCoordinates(); + + energy += weight * kappa_ * (v * curl); + + ////////////////////////////////////////////////////////////// + // Zeeman interaction term + ////////////////////////////////////////////////////////////// + v[2] -= 1; // subtract e_3 + energy += weight * 0.5 * h_ * v.two_norm2(); + + } + + return energy; +} + +} // namespace GFE + +} // namespace Dune +#endif + -- GitLab