Skip to content
Snippets Groups Projects
averagedistanceassemblertest.cc 4.37 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <config.h>
    
    #include <iostream>
    
    #include <dune/common/fvector.hh>
    #include <dune/grid/common/quadraturerules.hh>
    
    
    #include <dune/gfe/rotation.hh>
    #include <dune/gfe/realtuple.hh>
    #include <dune/gfe/unitvector.hh>
    
    #include <dune/gfe/localgeodesicfefunction.hh>
    
    
    // Domain dimension
    const int dim = 2;
    
    using namespace Dune;
    
    /** \brief Test whether interpolation is invariant under permutation of the simplex vertices
     */
    template <class TargetSpace>
    void testPoint(const std::vector<TargetSpace>& corners, 
                   const std::vector<double>& weights,
                   const TargetSpace& argument)
    {
        // create the assembler
        AverageDistanceAssembler<TargetSpace> assembler(corners, weights);
    
        // test the functional
        double value = assembler.value(argument);
        assert(!std::isnan(value));
        assert(value >= 0);
        
        // test the gradient
        typename TargetSpace::TangentVector gradient;
        assembler.assembleGradient(argument, gradient);
    
        // test the hessian
    
        FieldMatrix<double, TargetSpace::TangentVector::dimension, TargetSpace::TangentVector::dimension> hessian;
    
        FieldMatrix<double, TargetSpace::TangentVector::dimension, TargetSpace::TangentVector::dimension> hessianApproximation(0);
    
    
        assembler.assembleHessian(argument, hessian);
    
        //assembler.assembleHessianApproximation(argument, hessianApproximation);
    
    
        for (size_t i=0; i<hessian.N(); i++)
            for (size_t j=0; j<hessian.M(); j++) {
                assert(!std::isnan(hessian[i][j]));
                assert(!std::isnan(hessianApproximation[i][j]));
            }
    
    
        std::cout << "WARNING: no approximation of the Hessian available, not testing" << std::endl;
        return;
    
    
        FieldMatrix<double, TargetSpace::TangentVector::dimension, TargetSpace::TangentVector::dimension> diff = hessian;
    
        diff -= hessianApproximation;
        std::cout << "Matrix inf diff: " << diff.infinity_norm() << std::endl;
    }
    
    
    template <class TargetSpace>
    void testWeightSet(const std::vector<TargetSpace>& corners, 
                       const TargetSpace& argument)
    {
        // A quadrature rule as a set of test points
        int quadOrder = 3;
        
        const Dune::QuadratureRule<double, dim>& quad 
            = Dune::QuadratureRules<double, dim>::rule(GeometryType(GeometryType::simplex,dim), quadOrder);
        
        for (size_t pt=0; pt<quad.size(); pt++) {
            
            const Dune::FieldVector<double,dim>& quadPos = quad[pt].position();
            
            // local to barycentric coordinates
            std::vector<double> weights(dim+1);
            weights[0] = 1;
            for (int i=0; i<dim; i++) {
                weights[0] -= quadPos[i];
                weights[i+1] = quadPos[i];
            }
    
            testPoint(corners, weights, argument);
    
        }
    
    }
    
    
    void testRealTuples()
    {
    
        typedef RealTuple<double,1> TargetSpace;
    
    
        std::vector<TargetSpace> corners = {TargetSpace(1),
                                            TargetSpace(2),
                                            TargetSpace(3)};
    
        TargetSpace argument = corners[0];
        testWeightSet(corners, argument);
        argument = corners[1];
        testWeightSet(corners, argument);
        argument = corners[2];
        testWeightSet(corners, argument);
    }
    
    void testUnitVectors()
    {
    
        typedef UnitVector<double,3> TargetSpace;
    
    
        std::vector<TargetSpace> corners(dim+1);
    
        FieldVector<double,3> input;
        input[0] = 1;  input[1] = 0;  input[2] = 0;
        corners[0] = input;
        input[0] = 0;  input[1] = 1;  input[2] = 0;
        corners[1] = input;
        input[0] = 0;  input[1] = 0;  input[2] = 1;
        corners[2] = input;
    
        TargetSpace argument = corners[0];
        testWeightSet(corners, argument);
        argument = corners[1];
        testWeightSet(corners, argument);
        argument = corners[2];
        testWeightSet(corners, argument);
    }
    
    void testRotations()
    {
    
        typedef Rotation<double,3> TargetSpace;
    
    
        FieldVector<double,3> xAxis(0);
        xAxis[0] = 1;
        FieldVector<double,3> yAxis(0);
        yAxis[1] = 1;
        FieldVector<double,3> zAxis(0);
        zAxis[2] = 1;
    
    
        std::vector<TargetSpace> corners(dim+1);
    
        corners[0] = Rotation<double,3>(xAxis,0.1);
        corners[1] = Rotation<double,3>(yAxis,0.1);
        corners[2] = Rotation<double,3>(zAxis,0.1);
    
    
        TargetSpace argument = corners[0];
        testWeightSet(corners, argument);
        argument = corners[1];
        testWeightSet(corners, argument);
        argument = corners[2];
        testWeightSet(corners, argument);
    }
    
    
    int main()
    {
        testRealTuples();
        testUnitVectors();
        //testRotations();
    }