Skip to content
Snippets Groups Projects
compute-disc-error.cc 9.52 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <config.h>
    
    #include <dune/common/parametertree.hh>
    #include <dune/common/parametertreeparser.hh>
    
    #include <dune/grid/uggrid.hh>
    #include <dune/grid/io/file/gmshreader.hh>
    #include <dune/grid/utility/structuredgridfactory.hh>
    
    #include <dune/functions/functionspacebases/pqknodalbasis.hh>
    
    #include <dune/fufem/boundarypatch.hh>
    #include <dune/fufem/functiontools/basisinterpolator.hh>
    #include <dune/fufem/functiontools/boundarydofs.hh>
    #include <dune/fufem/functionspacebases/dunefunctionsbasis.hh>
    #include <dune/fufem/discretizationerror.hh>
    #include <dune/fufem/dunepython.hh>
    
    #include <dune/gfe/rotation.hh>
    #include <dune/gfe/unitvector.hh>
    #include <dune/gfe/realtuple.hh>
    #include <dune/gfe/embeddedglobalgfefunction.hh>
    #include <dune/gfe/cosseratvtkwriter.hh>
    
    // grid dimension
    const int dim = 2;
    const int dimworld = 2;
    
    // Image space of the geodesic fe functions
    const int targetDim = 3;
    // typedef Rotation<double,targetDim> TargetSpace;
    // typedef UnitVector<double,targetDim> TargetSpace;
    // typedef RealTuple<double,targetDim> TargetSpace;
    using TargetSpace = RigidBodyMotion<double,targetDim>;
    
    // Tangent vector of the image space
    const int blocksize = TargetSpace::TangentVector::dimension;
    
    using namespace Dune;
    
    template <class GridView, int order>
    void measureEOC(const GridView gridView,
                    const GridView referenceGridView,
                    const ParameterTree& parameterSet)
    {
      typedef std::vector<TargetSpace> SolutionType;
    
      //////////////////////////////////////////////////////////////////////////////////
      //  Construct the scalar function space bases corresponding to the GFE space
      //////////////////////////////////////////////////////////////////////////////////
    
      typedef Dune::Functions::PQkNodalBasis<GridView, order> FEBasis;
      FEBasis feBasis(gridView);
    
      //////////////////////////////////////////////////////////////////////////////////
    
      //  Read the data whose error is to be measured
    
      //////////////////////////////////////////////////////////////////////////////////
    
      // Input data
      typedef BlockVector<TargetSpace::CoordinateType> EmbeddedVectorType;
    
      EmbeddedVectorType embeddedX(feBasis.size());
      std::ifstream inFile(parameterSet.get<std::string>("simulationData"), std::ios_base::binary);
      if (not inFile)
        DUNE_THROW(IOError, "File " << parameterSet.get<std::string>("simulationData") << " could not be opened.");
      GenericVector::readBinary(inFile, embeddedX);
      inFile.close();
    
      SolutionType x(embeddedX.size());
      for (size_t i=0; i<x.size(); i++)
        x[i] = TargetSpace(embeddedX[i]);
    
      /////////////////////////////////////////////////////////////////
      //   Measure the discretization error
      /////////////////////////////////////////////////////////////////
    
      if (parameterSet.get<std::string>("discretizationErrorMode")=="analytical")
      {
    
        using FufemFEBasis = DuneFunctionsBasis<FEBasis>;
        FufemFEBasis fufemFEBasis(feBasis);
    
    
        // Read reference solution and its derivative into a PythonFunction
        typedef VirtualDifferentiableFunction<FieldVector<double, dim>, TargetSpace::CoordinateType> FBase;
    
        Python::Module module = Python::import(parameterSet.get<std::string>("referenceSolution"));
        auto referenceSolution = module.get("fdf").toC<std::shared_ptr<FBase>>();
    
        // The numerical solution, as a grid function
    
        GFE::EmbeddedGlobalGFEFunction<FufemFEBasis, TargetSpace> numericalSolution(fufemFEBasis, x);
    
    
        // QuadratureRule for the integral of the L^2 error
        QuadratureRuleKey quadKey(dim,6);
    
        // Compute the embedded L^2 error
    
        double l2Error = DiscretizationError<GridView>::computeL2Error(&numericalSolution,
                                                                       referenceSolution.get(),
                                                                       quadKey);
    
    
        // Compute the embedded H^1 error
    
        double h1Error = DiscretizationError<GridView>::computeH1HalfNormDifferenceSquared(gridView,
                                                                                           &numericalSolution,
                                                                                           referenceSolution.get(),
                                                                                           quadKey);
    
        std::cout << "elements: " << gridView.size(0)
    
                  << "      "
                  << "L^2 error: " << l2Error
                  << "      ";
        std::cout << "H^1 error: " << std::sqrt(l2Error*l2Error + h1Error) << std::endl;
      }
    
      if (parameterSet.get<std::string>("discretizationErrorMode")=="discrete")
      {
    
        FEBasis referenceFEBasis(referenceGridView);
    
        // Reference configuration
        EmbeddedVectorType embeddedReferenceX(referenceFEBasis.size());
        inFile.open(parameterSet.get<std::string>("referenceData"), std::ios_base::binary);
        if (not inFile)
          DUNE_THROW(IOError, "File " << parameterSet.get<std::string>("referenceData") << " could not be opened.");
        GenericVector::readBinary(inFile, embeddedReferenceX);
    
        SolutionType referenceX(embeddedReferenceX.size());
        for (size_t i=0; i<referenceX.size(); i++)
          referenceX[i] = TargetSpace(embeddedReferenceX[i]);
    
    
        using FufemFEBasis = DuneFunctionsBasis<FEBasis>;
        FufemFEBasis fufemReferenceFEBasis(referenceFEBasis);
        FufemFEBasis fufemFEBasis(feBasis);
    
        // The numerical solution, as a grid function
        GFE::EmbeddedGlobalGFEFunction<FufemFEBasis, TargetSpace> referenceSolution(fufemReferenceFEBasis, referenceX);
    
        // The numerical solution, as a grid function
        GFE::EmbeddedGlobalGFEFunction<FufemFEBasis, TargetSpace> numericalSolution(fufemFEBasis, x);
    
        double l2ErrorSquared = 0;
        double h1ErrorSquared = 0;
    
        HierarchicSearch<typename GridView::Grid,typename GridView::IndexSet> hierarchicSearch(gridView.grid(), gridView.indexSet());
    
        std::cout << "l2: " << l2ErrorSquared << std::endl;
        for (const auto& rElement : elements(referenceGridView))
        {
          const auto& quadRule = QuadratureRules<double, dim>::rule(rElement.type(), 6);
    
          for (const auto& qp : quadRule)
          {
            auto integrationElement = rElement.geometry().integrationElement(qp.position());
    
            auto globalPos = rElement.geometry().global(qp.position());
    
            auto element = hierarchicSearch.findEntity(globalPos);
            auto localPos = element.geometry().local(globalPos);
    
            auto diff = referenceSolution(rElement, qp.position()) - numericalSolution(element, localPos);
    
            l2ErrorSquared += integrationElement * qp.weight() * diff.two_norm2();
    
            auto derDiff = referenceSolution.derivative(rElement, qp.position()) - numericalSolution.derivative(element, localPos);
    
            h1ErrorSquared += integrationElement * qp.weight() * derDiff.frobenius_norm2();
    
          }
        }
        std::cout << "l2: " << l2ErrorSquared << std::endl;
    
        std::cout << "levels: " << gridView.grid().maxLevel()+1
                  << "      "
                  << "L^2 error: " << std::sqrt(l2ErrorSquared)
                  << "      "
                  << "H^1 error: " << std::sqrt(l2ErrorSquared + h1ErrorSquared)
                  << std::endl;
      }
    }
    
    
    int main (int argc, char *argv[]) try
    {
      // Start Python interpreter
      Python::start();
      Python::Reference main = Python::import("__main__");
      Python::run("import math");
    
      Python::runStream()
          << std::endl << "import sys"
          << std::endl << "sys.path.append('/home/sander/dune/dune-gfe/problems')"
          << std::endl;
    
      // parse data file
      ParameterTree parameterSet;
      if (argc < 2)
        DUNE_THROW(Exception, "Usage: ./compute-disc-error <parameter file>");
    
      ParameterTreeParser::readINITree(argv[1], parameterSet);
    
      ParameterTreeParser::readOptions(argc, argv, parameterSet);
    
      // Print all parameters, to have them in the log file
      parameterSet.report();
    
      /////////////////////////////////////////
      //    Create the grids
      /////////////////////////////////////////
      typedef UGGrid<dim> GridType;
    
      const int numLevels = parameterSet.get<int>("numLevels");
    
      shared_ptr<GridType> grid, referenceGrid;
    
      FieldVector<double,dimworld> lower(0), upper(1);
    
      if (parameterSet.get<bool>("structuredGrid"))
      {
        lower = parameterSet.get<FieldVector<double,dimworld> >("lower");
        upper = parameterSet.get<FieldVector<double,dimworld> >("upper");
    
        array<unsigned int,dim> elements = parameterSet.get<array<unsigned int,dim> >("elements");
        grid = StructuredGridFactory<GridType>::createCubeGrid(lower, upper, elements);
        referenceGrid = StructuredGridFactory<GridType>::createCubeGrid(lower, upper, elements);
      }
      else
      {
        std::string path                = parameterSet.get<std::string>("path");
        std::string gridFile            = parameterSet.get<std::string>("gridFile");
        grid = shared_ptr<GridType>(GmshReader<GridType>::read(path + "/" + gridFile));
        referenceGrid = shared_ptr<GridType>(GmshReader<GridType>::read(path + "/" + gridFile));
      }
    
      grid->globalRefine(numLevels-1);
      referenceGrid->globalRefine(parameterSet.get<int>("numReferenceLevels")-1);
    
      // Do the actual measurement
      const int order = parameterSet.get<int>("order");
      switch (order)
      {
        case 1:
        measureEOC<GridType::LeafGridView,1>(grid->leafGridView(), referenceGrid->leafGridView(), parameterSet);
        break;
    
        case 2:
        measureEOC<GridType::LeafGridView,2>(grid->leafGridView(), referenceGrid->leafGridView(), parameterSet);
        break;
    
        case 3:
        measureEOC<GridType::LeafGridView,3>(grid->leafGridView(), referenceGrid->leafGridView(), parameterSet);
        break;
    
        default:
          DUNE_THROW(NotImplemented, "Order '" << order << "' is not implemented");
      }
    
      return 0;
    }
    catch (Exception e)
    {
      std::cout << e << std::endl;
      return 1;
    }