Skip to content
Snippets Groups Projects
harmonicenergytest.cc 5.66 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "config.h"
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    #include <dune/grid/uggrid.hh>
    
    
    #include <dune/localfunctions/lagrange/pqkfactory.hh>
    
    
    #include <dune/gfe/unitvector.hh>
    #include <dune/gfe/harmonicenergystiffness.hh>
    
    #include "multiindex.hh"
    
    
    Oliver Sander's avatar
    Oliver Sander committed
    const int dim = 2;
    
    typedef UnitVector<3> TargetSpace;
    
    using namespace Dune;
    
    template <class GridType>
    void testEnergy(const GridType* grid, const std::vector<TargetSpace>& coefficients) {
    
    
        PQkLocalFiniteElementCache<double,double,GridType::dimension,1> feCache;
        typedef typename PQkLocalFiniteElementCache<double,double,GridType::dimension,1>::FiniteElementType LocalFiniteElement;
        
        //LocalGeodesicFEFunction<domainDim,double,LocalFiniteElement,TargetSpace> f(feCache.get(element),corners);
    
        
        HarmonicEnergyLocalStiffness<typename GridType::LeafGridView,LocalFiniteElement,TargetSpace> assembler;
    
    Oliver Sander's avatar
    Oliver Sander committed
        std::vector<TargetSpace> rotatedCoefficients(coefficients.size());
    
        for (int i=0; i<10; i++) {
    
            Rotation<3,double> rotation(FieldVector<double,3>(1), double(i));
    
            FieldMatrix<double,3,3> matrix;
            rotation.matrix(matrix);
            for (size_t j=0; j<coefficients.size(); j++) {
                FieldVector<double,3> tmp;
                matrix.mv(coefficients[j].globalCoordinates(), tmp);
                rotatedCoefficients[j] = tmp;
            }
    
            std::cout << "energy: " << assembler.energy(*grid->template leafbegin<0>(), 
    
                                                        feCache.get(grid->template leafbegin<0>()->type()),
    
    Oliver Sander's avatar
    Oliver Sander committed
                                                        rotatedCoefficients) << std::endl;
    
    
    Oliver Sander's avatar
    Oliver Sander committed
            std::vector<typename TargetSpace::EmbeddedTangentVector> rotatedGradient;
            assembler.assembleEmbeddedGradient(*grid->template leafbegin<0>(),
    
    Oliver Sander's avatar
    Oliver Sander committed
                                       rotatedCoefficients,
                                       rotatedGradient);
    
            for (size_t j=0; j<coefficients.size(); j++) {
                FieldVector<double,3> tmp;
                matrix.mtv(rotatedGradient[j], tmp);
                std::cout << "gradient: " << tmp << std::endl;
            }
    
        }
    
    
    Oliver Sander's avatar
    Oliver Sander committed
    }
    
    template <class GridType>
    void testGradientOfEnergy(const GridType* grid, const std::vector<TargetSpace>& coefficients)
    {
    
        PQkLocalFiniteElementCache<double,double,GridType::dimension,1> feCache;
        typedef typename PQkLocalFiniteElementCache<double,double,GridType::dimension,1>::FiniteElementType LocalFiniteElement;
        
        //LocalGeodesicFEFunction<domainDim,double,LocalFiniteElement,TargetSpace> f(feCache.get(element),corners);
        HarmonicEnergyLocalStiffness<typename GridType::LeafGridView,LocalFiniteElement,TargetSpace> assembler;
    
    
        std::vector<typename TargetSpace::EmbeddedTangentVector> gradient;
        assembler.assembleEmbeddedGradient(*grid->template leafbegin<0>(),
                                           coefficients,
                                           gradient);
    
        ////////////////////////////////////////////////////////////////////////////////////////
        //  Assemble finite difference approximation of the gradient
        ////////////////////////////////////////////////////////////////////////////////////////
    
        std::vector<typename TargetSpace::EmbeddedTangentVector> fdGradient;
        assembler.assembleEmbeddedFDGradient(*grid->template leafbegin<0>(),
                                           coefficients,
                                           fdGradient);
    
        double diff = 0;
        for (size_t i=0; i<fdGradient.size(); i++)
            diff = std::max(diff, (gradient[i] - fdGradient[i]).infinity_norm());
        
        if (diff > 1e-6) {
            
            std::cout << "gradient: " << std::endl;
            for (size_t i=0; i<gradient.size(); i++)
                std::cout << gradient[i] << std::endl;
        
            std::cout << "fd gradient: " << std::endl;
            for (size_t i=0; i<fdGradient.size(); i++)
                std::cout << fdGradient[i] << std::endl;
    
        }
        
    }
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    template <int domainDim>
    void testUnitVector3d()
    
    Oliver Sander's avatar
    Oliver Sander committed
    {
        // ////////////////////////////////////////////////////////
        //   Make a test grid consisting of a single simplex
        // ////////////////////////////////////////////////////////
    
    
    Oliver Sander's avatar
    Oliver Sander committed
        typedef UGGrid<domainDim> GridType;
    
    Oliver Sander's avatar
    Oliver Sander committed
    
        GridFactory<GridType> factory;
    
        FieldVector<double,dim> pos(0);
        factory.insertVertex(pos);
    
    
    Oliver Sander's avatar
    Oliver Sander committed
        for (int i=0; i<domainDim+1; i++) {
            pos = 0;
            pos[i] = 1;
            factory.insertVertex(pos);
        }
    
        std::vector<unsigned int> v(domainDim+1);
        for (int i=0; i<domainDim+1; i++)
            v[i] = i;
    
    Oliver Sander's avatar
    Oliver Sander committed
        factory.insertElement(GeometryType(GeometryType::simplex,dim), v);
    
        const GridType* grid = factory.createGrid();
        
    
        // //////////////////////////////////////////////////////////
        //  Test whether the energy is invariant under isometries
        // //////////////////////////////////////////////////////////
    
    
        int nTestPoints = 10;
        double testPoints[10][3] = {{1,0,0}, {0,1,0}, {-0.838114,0.356751,-0.412667},
                                   {-0.490946,-0.306456,0.81551},{-0.944506,0.123687,-0.304319},
                                   {-0.6,0.1,-0.2},{0.45,0.12,0.517},
                                   {-0.1,0.3,-0.1},{-0.444506,0.123687,0.104319},{-0.7,-0.123687,-0.304319}};
        
        // Set up elements of S^2
    
    Oliver Sander's avatar
    Oliver Sander committed
        std::vector<TargetSpace> coefficients(dim+1);
    
    
        MultiIndex index(dim+1, nTestPoints);
    
        int numIndices = index.cycle();
    
        for (int i=0; i<numIndices; i++, ++index) {
            
            for (int j=0; j<dim+1; j++) {
                Dune::array<double,3> w = {testPoints[index[j]][0], testPoints[index[j]][1], testPoints[index[j]][2]};
                coefficients[j] = UnitVector<3>(w);
            }
    
            testEnergy<GridType>(grid, coefficients);
    
            testGradientOfEnergy(grid, coefficients);
            
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    
    int main(int argc, char** argv)
    {
        testUnitVector3d<2>();
    }