From 2dc6fe3b25de8045e6463a8a8bccff93adad42be Mon Sep 17 00:00:00 2001 From: Oliver Sander <oliver.sander@tu-dresden.de> Date: Sat, 23 Jan 2016 06:19:46 +0100 Subject: [PATCH] New program to measure discretization errors Here is a new program that does nothing but compute discretization errors: that is L2 and H1 norms of differences between two functions. The reference function can be either discrete or given in closed form (the latter is not enabled yet). So far I have only used this program to measure discretization errors of Cosserat shell models, and I did *not* get the error behavior I expected. So either the error behavior of such shells is weird, or this new measurement program is still buggy. --- src/CMakeLists.txt | 3 +- src/compute-disc-error.cc | 260 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 src/compute-disc-error.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d74091c0..5adf4b8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ -set(programs cosserat-continuum +set(programs compute-disc-error + cosserat-continuum harmonicmaps mixed-cosserat-continuum rod-eoc diff --git a/src/compute-disc-error.cc b/src/compute-disc-error.cc new file mode 100644 index 00000000..f08b7cb9 --- /dev/null +++ b/src/compute-disc-error.cc @@ -0,0 +1,260 @@ +#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); + FEBasis referenceFEBasis(referenceGridView); + + ////////////////////////////////////////////////////////////////////////////////// + // Read the data whose error is to be measured, and the reference data + ////////////////////////////////////////////////////////////////////////////////// + + // 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]); + + // 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]); + + //CosseratVTKWriter<typename GridView::Grid>::template write<FEBasis>(feBasis,x, "cosserat_infile_" + std::to_string(gridView.grid().maxLevel()+1)); + + + ///////////////////////////////////////////////////////////////// + // Measure the discretization error + ///////////////////////////////////////////////////////////////// +#if 0 + if (parameterSet.get<std::string>("discretizationErrorMode")=="analytical") + { + // 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(feBasis, x); + + // QuadratureRule for the integral of the L^2 error + QuadratureRuleKey quadKey(dim,6); + + // Compute the embedded L^2 error + double l2Error = DiscretizationError<GridType::LeafGridView>::computeL2Error(&numericalSolution, + referenceSolution.get(), + quadKey); + + // Compute the embedded H^1 error + double h1Error = DiscretizationError<GridType::LeafGridView>::computeH1HalfNormDifferenceSquared(grid->leafGridView(), + &numericalSolution, + referenceSolution.get(), + quadKey); + + std::cout << "elements: " << grid->leafGridView().size(0) + << " " + << "L^2 error: " << l2Error + << " "; + std::cout << "H^1 error: " << std::sqrt(l2Error*l2Error + h1Error) << std::endl; + } +#endif + + if (parameterSet.get<std::string>("discretizationErrorMode")=="discrete") + { + std::cout << "FOO" << std::endl; + 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; +} -- GitLab