diff --git a/dune/gfe/assemblers/CMakeLists.txt b/dune/gfe/assemblers/CMakeLists.txt index cdfd6ade5b61b5d9181f8c0bc9de747b8fed0dcf..279a37476b2fef992cef984465c698e82edf2374 100644 --- a/dune/gfe/assemblers/CMakeLists.txt +++ b/dune/gfe/assemblers/CMakeLists.txt @@ -1,6 +1,5 @@ #install headers install(FILES - chiralskyrmionenergy.hh cosseratenergystiffness.hh cosseratrodenergy.hh geodesicfeassembler.hh diff --git a/dune/gfe/assemblers/chiralskyrmionenergy.hh b/dune/gfe/assemblers/chiralskyrmionenergy.hh deleted file mode 100644 index d88ef7e3fd1f3a388a893c626d5ffc9726934a10..0000000000000000000000000000000000000000 --- a/dune/gfe/assemblers/chiralskyrmionenergy.hh +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef DUNE_GFE_CHIRALSKYRMIONENERGY_HH -#define DUNE_GFE_CHIRALSKYRMIONENERGY_HH - -#include <dune/common/fmatrix.hh> -#include <dune/geometry/quadraturerules.hh> - -#include <dune/gfe/assemblers/localenergy.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 Basis, class LocalInterpolationRule, class field_type> - class ChiralSkyrmionEnergy - : public GFE::LocalEnergy<Basis,UnitVector<field_type,3> > - { - // various useful types - typedef UnitVector<field_type,3> TargetSpace; - typedef typename Basis::GridView GridView; - typedef typename GridView::ctype DT; - typedef typename TargetSpace::ctype RT; - typedef typename GridView::template Codim<0>::Entity Entity; - - // some other sizes - constexpr static int gridDim = GridView::dimension; - - public: - - ChiralSkyrmionEnergy(const Dune::ParameterTree& parameters) - { - h_ = parameters.template get<double>("h"); - kappa_ = parameters.template get<double>("kappa"); - } - - //! Dimension of a tangent space - constexpr static int blocksize = TargetSpace::TangentVector::dimension; - - /** \brief Assemble the energy for a single element */ - RT energy (const typename Basis::LocalView& localView, - const std::vector<TargetSpace>& localConfiguration) const override; - - RT energy (const typename Basis::LocalView& localView, - const typename Impl::LocalEnergyTypes<TargetSpace>::CompositeCoefficients& coefficients) const override - { - DUNE_THROW(NotImplemented, "!"); - } - - field_type h_; - field_type kappa_; - }; - - template <class Basis, class LocalInterpolationRule, class field_type> - typename ChiralSkyrmionEnergy<Basis, LocalInterpolationRule, field_type>::RT - ChiralSkyrmionEnergy<Basis, LocalInterpolationRule, field_type>:: - energy(const typename Basis::LocalView& localView, - const std::vector<TargetSpace>& localConfiguration) const - { - typedef typename GridView::template Codim<0>::Entity::Geometry Geometry; - - RT energy = 0; - - const auto element = localView.element(); - const auto& localFiniteElement = localView.tree().finiteElement(); - LocalInterpolationRule localInterpolationRule(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 = localInterpolationRule.evaluate(quadPos); - - // The derivative of the local function defined on the reference element - typename LocalInterpolationRule::DerivativeType referenceDerivative = localInterpolationRule.evaluateDerivative(quadPos,value); - - // The derivative of the function defined on the actual element - typename LocalInterpolationRule::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(); - - ////////////////////////////////////////////////////////////// - // Dzyaloshinskii-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 diff --git a/dune/gfe/densities/CMakeLists.txt b/dune/gfe/densities/CMakeLists.txt index e326ccc61a9c161ae43c3192e51e64f2ac0f1f4c..cea45c0e9d897b47477a9d570a8062154dff5b12 100644 --- a/dune/gfe/densities/CMakeLists.txt +++ b/dune/gfe/densities/CMakeLists.txt @@ -1,6 +1,7 @@ #install headers install(FILES bulkcosseratdensity.hh + chiralskyrmiondensity.hh cosseratshelldensity.hh harmonicdensity.hh localdensity.hh diff --git a/dune/gfe/densities/chiralskyrmiondensity.hh b/dune/gfe/densities/chiralskyrmiondensity.hh new file mode 100644 index 0000000000000000000000000000000000000000..82e4d8f10989805064c42bc569098cbf7c0501d8 --- /dev/null +++ b/dune/gfe/densities/chiralskyrmiondensity.hh @@ -0,0 +1,78 @@ +#ifndef DUNE_GFE_DENSITIES_CHIRALSKYRMIONDENSITY_HH +#define DUNE_GFE_DENSITIES_CHIRALSKYRMIONDENSITY_HH + +#include <dune/common/fmatrix.hh> +#include <dune/common/parametertree.hh> + +#include <dune/gfe/densities/localdensity.hh> + +namespace Dune::GFE +{ + + /** \brief Energy density of certain chiral Skyrmion model + * + * 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 Position, class field_type> + class ChiralSkyrmionDensity + : public GFE::LocalDensity<Position,UnitVector<field_type,3> > + { + // various useful types + using TargetSpace = UnitVector<field_type,3>; + using Derivative = FieldMatrix<field_type, TargetSpace::embeddedDim, Position::size()>; + + public: + + ChiralSkyrmionDensity(const Dune::ParameterTree& parameters) + { + h_ = parameters.template get<double>("h"); + kappa_ = parameters.template get<double>("kappa"); + } + + //! Dimension of a tangent space + constexpr static int blocksize = TargetSpace::TangentVector::dimension; + + /** \brief Evaluation with the current position, the deformation function, the deformation gradient, the rotation and the rotation gradient + * + * \param x The current position + * \param value The deformation at the current position + * \param derivative The derivative of the deformation at the current position + */ + virtual field_type operator() (const Position& x, + const TargetSpace& value, + const Derivative& derivative) const override + { + ////////////////////////////////////////////////////////////// + // Exchange energy (aka harmonic energy) + ////////////////////////////////////////////////////////////// + + field_type density = 0.5 * derivative.frobenius_norm2(); + + ////////////////////////////////////////////////////////////// + // Dzyaloshinskii-Moriya interaction term + ////////////////////////////////////////////////////////////// + + // derivative[a][b] contains the partial derivative of m_a in the direction x_b + FieldVector<field_type, 3> curl = {derivative[2][1], -derivative[2][0], derivative[1][0]-derivative[0][1]}; + + FieldVector<field_type, 3> v = value.globalCoordinates(); + + density += kappa_ * (v * curl); + + ////////////////////////////////////////////////////////////// + // Zeeman interaction term + ////////////////////////////////////////////////////////////// + v[2] -= 1; // subtract e_3 + density += 0.5 * h_ * v.two_norm2(); + + return density; + } + + private: + field_type h_; + field_type kappa_; + }; + +} // namespace Dune::GFE +#endif diff --git a/src/harmonicmaps.cc b/src/harmonicmaps.cc index 095cc200404c6568a10aa762b6ceb6df667810da..35a50711335bc48011f0de225e6582d1b5f0d341 100644 --- a/src/harmonicmaps.cc +++ b/src/harmonicmaps.cc @@ -43,8 +43,8 @@ #include <dune/gfe/localprojectedfefunction.hh> #include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh> #include <dune/gfe/assemblers/localintegralenergy.hh> -#include <dune/gfe/assemblers/chiralskyrmionenergy.hh> #include <dune/gfe/assemblers/geodesicfeassembler.hh> +#include <dune/gfe/densities/chiralskyrmiondensity.hh> #include <dune/gfe/densities/harmonicdensity.hh> #include <dune/gfe/riemanniantrsolver.hh> #include <dune/gfe/embeddedglobalgfefunction.hh> @@ -269,41 +269,37 @@ int main (int argc, char *argv[]) // //////////////////////////////////////////////////////////// typedef TargetSpace::rebind<adouble>::other ATargetSpace; - using GeodesicInterpolationRule = LocalGeodesicFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, ATargetSpace>; - using ProjectedInterpolationRule = GFE::LocalProjectedFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, ATargetSpace>; - - // Assembler using ADOL-C - std::shared_ptr<GFE::LocalEnergy<FEBasis,ATargetSpace> > localEnergy; + // First, the energy density std::string energy = parameterSet.get<std::string>("energy"); - if (energy == "harmonic") - { - auto harmonicDensity = std::make_shared<GFE::HarmonicDensity<GridType::Codim<0>::Entity::Geometry::LocalCoordinate, ATargetSpace> >(); - if (parameterSet["interpolationMethod"] == "geodesic") - localEnergy.reset(new GFE::LocalIntegralEnergy<FEBasis, GeodesicInterpolationRule, ATargetSpace>(harmonicDensity)); - else if (parameterSet["interpolationMethod"] == "projected") - localEnergy.reset(new GFE::LocalIntegralEnergy<FEBasis, ProjectedInterpolationRule, ATargetSpace>(harmonicDensity)); - else - DUNE_THROW(Exception, "Unknown interpolation method " << parameterSet["interpolationMethod"] << " requested!"); + using LocalCoordinate = GridType::Codim<0>::Entity::Geometry::LocalCoordinate; + std::shared_ptr<GFE::LocalDensity<LocalCoordinate,ATargetSpace> > density; - } else if (energy == "chiral_skyrmion") + if (energy == "harmonic") { - // // Doesn't work: we are not inside of a template - // if constexpr (std::is_same<TargetSpace, UnitVector<double,3> >::value) - // { - if (parameterSet["interpolationMethod"] == "geodesic") - localEnergy.reset(new GFE::ChiralSkyrmionEnergy<FEBasis, GeodesicInterpolationRule, adouble>(parameterSet.sub("energyParameters"))); - else if (parameterSet["interpolationMethod"] == "projected") - localEnergy.reset(new GFE::ChiralSkyrmionEnergy<FEBasis, ProjectedInterpolationRule, adouble>(parameterSet.sub("energyParameters"))); - else - DUNE_THROW(Exception, "Unknown interpolation method " << parameterSet["interpolationMethod"] << " requested!"); - // } else - // DUNE_THROW(Exception, "Build program with TargetSpace = UnitVector<3> for the ChiralSkyrmion energy!"); - + density = std::make_shared<GFE::HarmonicDensity<LocalCoordinate, ATargetSpace> >(); + } + else if (energy == "chiral_skyrmion") + { + density = std::make_shared<GFE::ChiralSkyrmionDensity<LocalCoordinate, adouble> >(parameterSet.sub("energyParameters")); } else DUNE_THROW(Exception, "Unknown energy type '" << energy << "'"); + // Next: The local energy, i.e., the integral of the density over one element + using GeodesicInterpolationRule = LocalGeodesicFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, ATargetSpace>; + using ProjectedInterpolationRule = GFE::LocalProjectedFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, ATargetSpace>; + + std::shared_ptr<GFE::LocalEnergy<FEBasis,ATargetSpace> > localEnergy; + + if (parameterSet["interpolationMethod"] == "geodesic") + localEnergy = std::make_shared<GFE::LocalIntegralEnergy<FEBasis, GeodesicInterpolationRule, ATargetSpace> >(density); + else if (parameterSet["interpolationMethod"] == "projected") + localEnergy = std::make_shared<GFE::LocalIntegralEnergy<FEBasis, ProjectedInterpolationRule, ATargetSpace> >(density); + else + DUNE_THROW(Exception, "Unknown interpolation method " << parameterSet["interpolationMethod"] << " requested!"); + + // Compute local tangent problems by applying ADOL-C directly to the energy on the element LocalGeodesicFEADOLCStiffness<FEBasis,TargetSpace> localGFEADOLCStiffness(localEnergy.get()); GeodesicFEAssembler<FEBasis,TargetSpace> assembler(feBasis, localGFEADOLCStiffness);