From d5ab0ae425f11ca83dbc88c1a0056420336df248 Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn <robertk@posteo.net> Date: Wed, 8 Oct 2014 21:16:10 +0200 Subject: [PATCH] copy poisson implementation from dglagrange. Not working yet. --- dune/fem-dg/test/poisson/Makefile.am | 74 ++ dune/fem-dg/test/poisson/benchmark.cc | 1160 ++++++++++++++++++ dune/fem-dg/test/poisson/benchmark.hh | 1118 +++++++++++++++++ dune/fem-dg/test/poisson/benchmarkproblem.hh | 266 ++++ dune/fem-dg/test/poisson/models.hh | 500 ++++++++ dune/fem-dg/test/poisson/passtraits.hh | 105 ++ dune/fem-dg/test/poisson/problemcreator.hh | 197 +++ 7 files changed, 3420 insertions(+) create mode 100644 dune/fem-dg/test/poisson/Makefile.am create mode 100644 dune/fem-dg/test/poisson/benchmark.cc create mode 100644 dune/fem-dg/test/poisson/benchmark.hh create mode 100644 dune/fem-dg/test/poisson/benchmarkproblem.hh create mode 100644 dune/fem-dg/test/poisson/models.hh create mode 100644 dune/fem-dg/test/poisson/passtraits.hh create mode 100644 dune/fem-dg/test/poisson/problemcreator.hh diff --git a/dune/fem-dg/test/poisson/Makefile.am b/dune/fem-dg/test/poisson/Makefile.am new file mode 100644 index 00000000..31057579 --- /dev/null +++ b/dune/fem-dg/test/poisson/Makefile.am @@ -0,0 +1,74 @@ +# install these headers +poissondir=$(includedir)/test/advdiff +poisson_HEADERS = models.hh problemcreator.hh steppertraits.hh + +LDADD = $(ALL_PKG_LDFLAGS) $(ALL_PKG_LIBS) $(LOCAL_LIBS) $(DUNEMPILDFLAGS) $(DUNEMPILIBS) + +BASEDIR=../../main + +#GRIDTYPE = ALUGRID_SIMPLEX +GRIDTYPE = YASPGRID +#GRIDTYPE=PARALLELGRID_ALUGRID_SIMPLEX +#GRIDTYPE=CARTESIANGRID_ALUGRID_CUBE +#GRIDTYPE = SPGRID +POLORDER = 2 +GRIDDIM = 2 +DIMRANGE = 1 +FLUX = 1 # LLF 1, HLL 2 + +#USE_OMP=-fopenmp + +# INFO SPACE OPERATOR: +# 1. define PRIMALDG for IP, BR2, CDG, CDG2 +# 2. define DUALDG for LDG +# INFO TRACK LIFTING: +# 1. define LOCALDEBUG to calculate \sum_e\int_Omega(r_e*l_e) and +# \sum_e\int_Omega(r_e*l_e). They will be output to std::cout from the Stepper +# INFO TESTOPERATOR: +# 1. define TESTOPERATOR for linear advdiff equation to output various +# information on space operator +EXTRA_PROGRAMS = advdiff pulse # quasiadvdiff quasiadvdiff12 plaplace plaplace12 +check_PROGRAMS = advdiffonep pulseonep # quasiadvdiff quasiadvdiff12 plaplace plaplace12 + +advdiff_SOURCES = $(BASEDIR)/main.cc $(BASEDIR)/main_1.cc $(BASEDIR)/main_2.cc \ + $(BASEDIR)/main_0.cc $(BASEDIR)/main_3.cc +advdiffonep_SOURCES = $(BASEDIR)/main.cc $(BASEDIR)/main_pol.cc + +pulse_SOURCES = $(BASEDIR)/main.cc $(BASEDIR)/main_1.cc $(BASEDIR)/main_2.cc \ + $(BASEDIR)/main_0.cc $(BASEDIR)/main_3.cc +pulseonep_SOURCES = $(BASEDIR)/main.cc $(BASEDIR)/main_pol.cc + +AM_CPPFLAGS = $(USE_OMP) -I../../problems/advdiff $(ALL_PKG_CPPFLAGS) -DGRIDDIM=$(GRIDDIM) \ + -D$(GRIDTYPE) $(DUNEMPICPPFLAGS) \ + -DDIMRANGE=$(DIMRANGE) -DFLUX=$(FLUX) -DPRIMALDG -DUSE_ASSERT_THROW +AM_LDFLAGS = $(ALL_PKG_LDFLAGS) $(LAPACK_LDFLAGS) $(USE_OMP) + +advdiff_CPPFLAGS = $(AM_CPPFLAGS) +advdiffonep_CPPFLAGS = $(advdiff_CPPFLAGS) -DONLY_ONE_P -DPOLORDER=$(POLORDER) + +pulse_CPPFLAGS = $(AM_CPPFLAGS) +pulseonep_CPPFLAGS = $(advdiff_CPPFLAGS) -DONLY_ONE_P -DPOLORDER=$(POLORDER) + +DISTCHECK_CONFIGURE_FLAGS = DOXYGEN="true" + +EXTRA_DIST = parameter + +CLEANFILES=manager.*.log eoc_*.tex + +PROG=advdiffonep +# codegeneration +generatecode: + $(MAKE) -i clean + $(MAKE) CXXFLAGS="-O0 -Wall -DNDEBUG -DBASEFUNCTIONSET_CODEGEN_GENERATE" $(PROG) + ./$(PROG) femhowto.maximaltimesteps:1 fem.io.outputformat:none codegenparameter + +# compile fast code +compilecode: + $(MAKE) clean + $(MAKE) CXXFLAGS="$(CXXFLAGS) -DUSE_BASEFUNCTIONSET_CODEGEN" $(PROG) + +codegen: + $(MAKE) generatecode + $(MAKE) compilecode + +include $(top_srcdir)/am/global-rules diff --git a/dune/fem-dg/test/poisson/benchmark.cc b/dune/fem-dg/test/poisson/benchmark.cc new file mode 100644 index 00000000..07caba2a --- /dev/null +++ b/dune/fem-dg/test/poisson/benchmark.cc @@ -0,0 +1,1160 @@ +#ifndef FVCA5_BENCHMARK_CC +#define FVCA5_BENCHMARK_CC + +#include <cmath> +#include <dune/common/exceptions.hh> +#include "benchmark.hh" + +template <int dim, class DomainField, class Field> +class BenchMark_1 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + Field factor_[dim][dim]; +public: + virtual ~BenchMark_1() {} + BenchMark_1(Field globalShift, Field factor) + : globalShift_( globalShift ) + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + if( i == j ) factor_[i][j] = 1.5; + else if( std::abs( i - j ) == 1 ) factor_[i][j] = 0.5; + else factor_[i][j] = 0; + } + } + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + // copy values + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + k[i][j] = factor_[i][j]; + } + } + + virtual Field rhs (const DomainField arg[dim]) const + { + double x = arg[0]; + double y = arg[1]; + + double uxx = -2.*y*(1-y)*16.; + double uxy = (-2.*x+1)*(-2.*y+1)*16.; + double uyy = -2.*x*(1-x)*16.; + + return -( factor_[0][0] * uxx + factor_[0][1] * uxy + factor_[1][0] * uxy + factor_[1][1] * uyy); + } + + virtual Field exact(const DomainField x[dim]) const + { + Field val = 16.; + for(int i=0; i<dim; ++i) + val *= (x[i] - (x[i]*x[i])); + val += globalShift_ ; + return val; + } + + virtual void gradExact(const DomainField arg[dim], Field grad[dim] ) const + { + double x = arg[0]; + double y = arg[1]; + + grad[0] = (-2.*x+1)*y*(1-y)*16.; + grad[1] = (-2.*y+1)*x*(1-x)*16.; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_1_2 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + Field factor_[dim][dim]; +public: + virtual ~BenchMark_1_2() {} + BenchMark_1_2(Field globalShift, Field factor) + : globalShift_(0.0) + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + if( i == j ) factor_[i][j] = 1.5; + else factor_[i][j] = 0.5; + } + } + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_[i][i]; + for(int j=0; j<i; ++j) k[i][j] = factor_[i][j]; + for(int j=i+1; j<dim; ++j) k[i][j] = factor_[i][j]; + } + } + + + virtual Field rhs (const DomainField arg[dim]) const + { + double x1 = 1.-arg[0]; + double y1 = 1.-arg[1]; + + double uxx = -y1*y1*sin(x1*y1) + 6.*x1* y1*y1; + double uxy = -x1*y1*sin(x1*y1) + cos(x1*y1) + 6.*y1* x1*x1; + double uyy = -x1*x1*sin(x1*y1) + 2.* x1*x1*x1; + return -(factor_[0][0] * uxx + factor_[0][1]*uxy + factor_[1][0]* uxy + factor_[1][1]*uyy); + } + + virtual Field exact(const DomainField arg[dim]) const + { + double x1 = 1.-arg[0]; + double y1 = 1.-arg[1]; + return sin(x1*y1) + x1*x1*x1 * y1*y1; + } + + virtual void gradExact(const DomainField arg[dim], Field grad[dim] ) const + { + double x1 = 1.-arg[0]; + double y1 = 1.-arg[1]; + + grad[0] = -y1*cos(x1*y1) - 3.* (x1*y1)* (x1*y1); + grad[1] = -x1*cos(x1*y1) - 2.*y1* x1*x1*x1; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_2 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + Field factor_[dim][dim]; + const Field delta_; + const Field sqrtDelta_; + const Field x1_; + const Field x2_; +public: + virtual ~BenchMark_2() {} + BenchMark_2(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(factor) + , sqrtDelta_( sqrt(delta_) ) + , x1_ ( 8. * atan(1.) ) + , x2_ ( x1_ / sqrtDelta_ ) + { + factor_[0][0] = 1; + factor_[0][1] = factor_[1][0] = 0.0; + factor_[1][1] = delta_; + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_[i][i]; + for(int j=0; j<i; ++j) k[i][j] = factor_[i][j]; + for(int j=i+1; j<dim; ++j) k[i][j] = factor_[i][j]; + } + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + return sin(x1_* x[0])*exp(-x2_* x[1]); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = x1_ * cos(x1_* x[0])*exp(-x2_ * x[1]); + grad[1] = -x2_ * exact(x); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact(x); + // we have only neumann boundary here (see discretemodel.hh) + return true; + //return false; + } +}; + + + +template <int dim, class DomainField, class Field> +class BenchMark_3 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + Field factor_[dim][dim]; + const Field delta_; + const Field pi_; + const Field cost_; + const Field sint_; +public: + virtual ~BenchMark_3() {} + BenchMark_3(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(1e-3) + , pi_ ( 4. * atan(1.) ) + , cost_ ( cos( 40. * pi_ / 180. ) ) + , sint_ ( sqrt(1. - cost_*cost_) ) + { + factor_[0][0] = cost_*cost_+delta_*sint_*sint_; + factor_[1][0] = factor_[0][1] = cost_*sint_*(1.-delta_); + factor_[1][1] = sint_*sint_+delta_*cost_*cost_; + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_[i][i]; + for(int j=0; j<i; ++j) k[i][j] = factor_[i][j]; + for(int j=i+1; j<dim; ++j) k[i][j] = factor_[i][j]; + } + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + double bndFunc (const double x, + const double lower, + const double upper, + const double lowval, + const double upval) const + { + if( x <= lower ) return lowval; + if( x >= upper ) return upval; + + const double scale = (x - lower)/(upper - lower); + assert( scale >= 0 && scale <= 1 ); + + return (1. - scale) * lowval + scale * upval; + } + + virtual Field exact(const DomainField x[dim]) const + { + const int bndId = this->getBoundaryId( x , x ); + if( bndId == 0 ) + { + return bndFunc(x[1],0.2,0.3,1,0.5); + } + else if( bndId == 1 ) + { + return bndFunc(x[1],0.7,0.8,0.5,0); + } + else if( bndId == 2 ) + { + return bndFunc(x[0],0.2,0.3,1,0.5); + } + else if( bndId == 3 ) + { + return bndFunc(x[0],0.7,0.8,0.5,0); + } + return 0.5; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 0.0; + grad[1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + // only dirichlet for this problem + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_4 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; +public: + virtual ~BenchMark_4() {} + BenchMark_4(Field globalShift, Field factor) + : globalShift_(0.0) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + for(int j=0; j<dim; ++j ) + k[i][j] = 0; + + if( omega1(x) ) + { + k[0][0] = 1e2; + k[1][1] = 1e1; + if( dim > 2 ) + { + k[2][2] = 1e3; + k[0][1] = 0.5; + k[1][0] = 0.5; + k[1][2] = 5; + k[2][1] = 5; + } + } + else + { + k[0][0] = 1e-2; + k[1][1] = 1e-3; + if( dim > 2 ) + { + //k[0][1] = 1e-1; + //k[1][0] = 1e-1; + //k[1][2] = 1e-2; + //k[2][1] = 1e-2; + k[2][2] = 1e-2; + } + } + } + + bool omega1(const DomainField x[dim]) const + { + if( dim == 2 ) + { + if (x[0] <= 0.5) + { + int inty = int(10.0 * (x[1] + 0.15)); + // if even then omega1 else omega2 + return ((inty%2) == 0); + } + else + { + int inty = int(10.0 * x[1]); + // if even then omega1 else omega2 + return ((inty%2) == 0); + } + } + else if ( dim == 3 ) + { + if (x[0] <= 0.5) + { + int inty = int(16.0 * (x[1] + 0.0625)); + // if even then omega1 else omega2 + return ((inty%2) == 0); + } + else + { + int inty = int(16.0 * x[1]); + // if even then omega1 else omega2 + return ((inty%2) == 0); + } + } + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + double val = (1.0 - x[0]); + if( dim > 2 ) + val *= (1 - x[2]); + return val; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 0.0; + grad[1] = 0.0; + grad[dim-1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_5 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field delta_; + const Field pi; +public: + virtual ~BenchMark_5() {} + BenchMark_5(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(1e-3) + , pi ( 4. * atan(1.) ) + { + } + + virtual bool constantLocalK () const { return false; } + + virtual void K(const DomainField arg[dim], Field k[dim][dim] ) const + { + double x = arg[0]; + double y = arg[1]; + double rt = x*x+y*y; + k[0][0] = (y*y+delta_*x*x)/rt; + k[1][1] = (x*x+delta_*y*y)/rt; + k[1][0] = k[0][1] = -(1-delta_)*x*y/rt; + } + + virtual Field rhs (const DomainField arg[dim]) const + { + Field k[dim][dim]; + K(arg,k); + double x = arg[0]; + double y = arg[1]; + double rt = x*x+y*y; + + double ux = pi * cos(pi*x)*sin(pi*y); + double uy = pi * cos(pi*y)*sin(pi*x); + + double f0 = sin(pi*x)*sin(pi*y)*pi*pi*(1+delta_)*(x*x+y*y) + + cos(pi*x)*sin(pi*y)*pi*(1.-3.*delta_)*x + + cos(pi*y)*sin(pi*x)*pi*(1.-3.*delta_)*y + + cos(pi*y)*cos(pi*x)*2.*pi*pi*(1.-delta_)*x*y; + double kxx = k[0][0]; + double kyy = k[1][1]; + double kxy = k[0][1]; + return (f0+2.*(x*(kxx*ux+kxy*uy)+y*(kxy*ux+kyy*uy)))/rt; + } + + virtual Field exact(const DomainField x[dim]) const + { + return sin(pi*x[0])*sin(pi*x[1]); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = pi * cos(pi*x[0])*sin(pi*x[1]); + grad[1] = pi * cos(pi*x[1])*sin(pi*x[0]); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_6 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field delta_; + const Field cost_; + const Field sint_; +public: + virtual ~BenchMark_6() {} + BenchMark_6(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(0.2) + , cost_ ( 1./sqrt(1.+delta_*delta_) ) + , sint_ ( delta_*cost_ ) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + double phi1 = x[1] - delta_ * (x[0] - .5) - .475; + double phi2 = phi1 - .05; + + double alpha = 0.0; + double beta = 0.0; + if (phi1<0 || phi2>0) + { + alpha = 1.0; + beta = 0.1; + } + else + { + alpha = 100.0; + beta = 10.0; + } + + k[0][0] = alpha*cost_*cost_+beta*sint_*sint_; + k[0][1] = k[1][0] = cost_*sint_*(alpha-beta); + k[1][1] = alpha*sint_*sint_+beta*cost_*cost_; + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + return - x[0] - x[1] * delta_; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = -1.0; + grad[1] = -delta_; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + // we have neumann boundary here + return true; + } +}; + + +template <int dim, class DomainField, class Field> +class BenchMark_7 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field delta_; +public: + virtual ~BenchMark_7() {} + BenchMark_7(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(0.2) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + double phi1 = phi(x); + double phi2 = phi1 - .05; + + int dom = domain( phi1, phi2 ); + if( dom == 1 || dom == 3 ) + { + k[0][0] = k[1][1] = 1; + k[1][0] = k[0][1] = 0; + } + else + { + k[0][0] = k[1][1] = 0.01; + k[1][0] = k[0][1] = 0; + } + } + + double phi(const DomainField x[dim]) const + { + return x[1] - delta_ * (x[0] - .5) - .475; + } + + int domain(const double phi1, const double phi2) const + { + if (phi1<0) + return 1; + else if (phi2<0) + return 2; + else + return 3; + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + double phi1 = phi(x); + double phi2 = phi1 - .05; + + int dom = domain( phi1, phi2 ); + if( dom == 1 ) + { + return -phi1; + } + else if( dom == 2 ) + { + return -phi1/.01; + } + else + { + return -phi2 - 5.; + } + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + double phi1 = phi(x); + double phi2 = phi1 - .05; + int dom = domain( phi1, phi2 ); + if( dom == 1 || dom == 3 ) + { + grad[0] = delta_; + grad[1] = -1.0; + } + else // if (dom == 2) + { + grad[0] = delta_/.01; + grad[1] = - 1./.01; + } + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + +#if PROBLEM_8 +#include <dune/fem/gridpart/gridpart.hh> +#include <dune/fem/space/fvspace.hh> +#include <dune/fem/space/lagrangespace.hh> +#include <dune/fem/function/adaptivefunction.hh> + +typedef LeafGridPart<GridType> ParamGridPartType; +typedef FunctionSpace<double,double,GridType::dimension,1> ParamFunctionSpaceType; +typedef LagrangeDiscreteFunctionSpace<ParamFunctionSpaceType,ParamGridPartType,2> + ParamDiscreteFunctionSpaceType; +// typedef FiniteVolumeSpace<ParamFunctionSpaceType,ParamGridPartType,0> +// ParamDiscreteFunctionSpaceType; +typedef AdaptiveDiscreteFunction<ParamDiscreteFunctionSpaceType> + ParamDiscreteFunctionType; +ParamDiscreteFunctionType* paramDiscreteFunction; + + +template <int dim, class DomainField, class Field> +class BenchMark_8 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field delta_; +public: + virtual ~BenchMark_8() {} + BenchMark_8(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(0.) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + k[0][0] = k[1][1] = 1; + k[1][0] = k[0][1] = 0; + } + + virtual Field rhs (const DomainField arg[dim]) const + { + FieldVector<double,dim> p(0); + FieldVector<double,1> ret(0); + p[0] = arg[0]; + p[1] = arg[1]; + + const ParamGridPartType& gridPart = paramDiscreteFunction->space().gridPart(); + const typename ParamGridPartType::IndexSetType& index = gridPart.indexSet(); + HierarchicSearch<GridType,ParamGridPartType::IndexSetType> + search(gridPart.grid(),index); + typename ParamDiscreteFunctionType::LocalFunctionType lf = + paramDiscreteFunction->localFunction((*(search.findEntity(p)))); + + lf.evaluate(search.findEntity(p)->geometry().local(p),ret); + /* + std::cout << search.findEntity(p)->geometry().local(p) + << " " << p + << " " << ret[0] << std::endl; + */ + return ret[0]; + } + + virtual Field exact(const DomainField x[dim]) const + { + return 0.0; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 0.0; + grad[1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = 0.0; + return true; + } + virtual int getBoundaryId(const DomainField x[dim], + const DomainField n[dim]) const + { + if (std::abs(n[0]) > 1e-8) { + if (n[1] < 0.) return 0; + else return 1; + } + if (std::abs(n[0]) < 1e-8) { + if (n[1] < 0.) return 2; + else return 3; + } + abort(); + return 0; + } +}; +#endif + +template <int dim, class DomainField, class Field> +class BenchMark_9 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field delta_; +public: + virtual ~BenchMark_9() {} + BenchMark_9(Field globalShift, Field factor) + : globalShift_(0.0) + , delta_(0.) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + k[0][0] = k[1][1] = 1; + k[1][0] = k[0][1] = 0; + } + + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.; + } + + virtual Field exact(const DomainField x[dim]) const + { + return 0.0; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 0.0; + grad[1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = (x[0]<0.6)?1.:0.; + if (x[0]<=0 || x[0]>=1) + return false; + if (x[1]<=0 || x[1]>=1) + return false; + return true; + } +}; + + +///////////////////////////////////////////////////////////////////// +// +// 3D Benchmark Problems +// +///////////////////////////////////////////////////////////////////// +template <int dim, class DomainField, class Field> +class BenchMark3d_1 : public DataFunctionIF<dim,DomainField,Field> +{ + + Field K_[dim][dim]; +public: + virtual ~BenchMark3d_1() {} + BenchMark3d_1(Field globalShift, Field factor) + { + if( dim != 3 ) + { + DUNE_THROW(Dune::NotImplemented,"Problem only implemented for dim=3"); + } + + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + if( i == j ) K_[i][j] = 1.0; + else if( std::abs( i - j ) == 1 ) + { + K_[i][j] = 0.5; + } + else K_[i][j] = 0; + } + } + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + // just copy tensor + for(int i=0; i<dim; ++i) + for(int j=0; j<dim; ++j) + k[i][j] = K_[i][j]; + } + + virtual Field rhs (const DomainField x[dim]) const + { + return M_PI*M_PI*(3.0*sin(M_PI*x[0])*sin(M_PI*(x[1]+0.5))*sin(M_PI*(x[2]+(1.0/3.0))) + -cos(M_PI*x[0])*cos(M_PI*(x[1]+0.5))*sin(M_PI*(x[2]+(1.0/3.0))) + -sin(M_PI*x[0])*cos(M_PI*(x[1]+0.5))*cos(M_PI*(x[2]+(1.0/3.0)))); + } + + virtual Field exact(const DomainField x[dim]) const + { + return 1.0+sin(M_PI*x[0])*sin(M_PI*(x[1]+0.5))*sin(M_PI*(x[2]+(1.0/3.0))); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = M_PI*cos(M_PI*x[0])*sin(M_PI*(x[1]+0.5))*sin(M_PI*(x[2]+(1.0/3.0))); + grad[1] = M_PI*sin(M_PI*x[0])*cos(M_PI*(x[1]+0.5))*sin(M_PI*(x[2]+(1.0/3.0))); + grad[2] = M_PI*sin(M_PI*x[0])*sin(M_PI*(x[1]+0.5))*cos(M_PI*(x[2]+(1.0/3.0))); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } + +}; + + +template <int dim, class DomainField, class Field> +class BenchMark3d_3 : public DataFunctionIF<dim,DomainField,Field> +{ + + Field K_[dim][dim]; +public: + virtual ~BenchMark3d_3() {} + BenchMark3d_3(Field globalShift, Field factor) + { + if( dim != 3 ) + { + DUNE_THROW(Dune::NotImplemented,"Problem only implemented for dim=3"); + } + + for(int i=0; i<dim; ++i) + for(int j=0; j<dim; ++j) + K_[ i ][ j ] = 0 ; + + // set diagonal + K_[0][0] = 1; + K_[1][1] = 1; + K_[2][2] = 1e3 ; + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + k[i][j] = K_[i][j]; + } + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + return 1002.0*4.0*M_PI*M_PI*sin(2.0*M_PI*x[0])*sin(2.0*M_PI*x[1])*sin(2.0*M_PI*x[2]); + } + + virtual Field exact(const DomainField x[dim]) const + { + return sin(2.0*M_PI*x[0])*sin(2.0*M_PI*x[1])*sin(2.0*M_PI*x[2]); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + const Field pi2 = 2.0*M_PI; + grad[0] = pi2 * cos( pi2 * x[0]) * sin( pi2 * x[1]) * sin( pi2 * x[2]); + grad[1] = pi2 * sin( pi2 * x[0]) * cos( pi2 * x[1]) * sin( pi2 * x[2]); + grad[2] = pi2 * sin( pi2 * x[0]) * sin( pi2 * x[1]) * cos( pi2 * x[2]); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } + +}; + + +template <int dim, class DomainField, class Field> +class BenchMark3d_4 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field tau_ ; +public: + virtual ~BenchMark3d_4() {} + BenchMark3d_4(Field globalShift, Field factor) + : tau_( 0.2 ) + { + if( dim != 3 ) + { + DUNE_THROW(Dune::NotImplemented,"Problem only implemented for dim=3"); + } + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + for(int j=0; j<dim; ++j ) + k[i][j] = 0; + + for(int i=0; i<2; ++ i ) k[i][i] = 1; + k[2][2] = tau_ ; + } + + int getDomain(const DomainField x[dim]) const + { + return 0; + } + + virtual Field rhs (const DomainField arg[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + Field u,u_x,u_y,u_z; + calculsolwell(x[0],x[1],x[2],u,u_x,u_y,u_z,1.0,0.0,0.0,1.0,0.0,tau_); + return u; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + Field u,u_x,u_y,u_z; + calculsolwell(x[0],x[1],x[2],u,u_x,u_y,u_z,1.0,0.0,0.0,1.0,0.0,tau_); + grad[0] = u_x; + grad[1] = u_y; + grad[dim-1] = u_z; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } + + void calculsolwell (Field x, Field y, Field z, + Field& p, Field& px, Field& py, Field& pz, + Field lxx, Field lxy, Field lxz, Field lyy, Field lyz, Field lzz) const + { + Field alpha,mu0, + A11,A12,A13,A21,A22,A23,A31,A32,A33, + //XX, + YY,ZZ,s2,a2,a1,a0,sh,frho,mu,ch,frho_p, + GP_X,GP_Y,GP_Z; + + alpha = 1.0; + mu0 = 1.85334252045523; + + lxx = 1.; + lyy = 1.; + lzz = 0.2; + lxy = 0.; + lxz = 0.; + lyz = 0.; + + A11 = 0.122859140982213; + A12 = 0.0; + A13 = -1.68776357811111; + A21 = 0.0; + A22 = 0.76472449133173; + A23 = 0.0; + A31 = 0.754790818120945; + A32 = 0.0; + A33 = 0.274721390893459; + + a2 = 0.000603774740915493; + + + //------------------------------------------------- + // Eval solution + //------------------------------------------------- + //XX = A11*x+A12*y+A13*z; + YY = A21*x+A22*y+A23*z; + ZZ = A31*x+A32*y+A33*z; + + // computation of s2 = sh^2, solution to + + // a2 S^2 + a1 S + a0 = 0 + + a1 = a2 - ZZ*ZZ - YY*YY; + + a0 = - YY*YY; + + s2 = (-a1+sqrt(a1*a1 - 4.0*a0*a2))/(2.0*a2); + + sh = sqrt(s2); + + // argsh(w) = log(w+sqrt(w**2+1)) + + frho = sh+sqrt(s2+1.0); + + mu = log(frho); + + p = alpha *(mu - mu0); + + //------------------------------------------------- + // Eval gradient + //------------------------------------------------- + ch = (frho+1.0/frho)*0.5; + + frho_p = alpha /( (ZZ*ZZ*sh)/(ch*ch*ch) + (YY*YY*ch)/(sh*sh*sh) ); + + GP_X = 0.0; + GP_Y = frho_p * YY / ( sh * sh ); + GP_Z = frho_p * ZZ / ( ch * ch ); + + px = A11*GP_X + A21*GP_Y + A31*GP_Z; + py = A12*GP_X + A22*GP_Y + A32*GP_Z; + pz = A13*GP_X + A23*GP_Y + A33*GP_Z; + } + +}; + + +template <int dim, class DomainField, class Field> +class BenchMark3d_5 : public DataFunctionIF<dim,DomainField,Field> +{ + enum { numDomain = 4 }; + Field tensor_[ numDomain ][ dim ]; + Field alpha_[ numDomain ]; + Field trace_[ numDomain ]; + const Field pi2_ ; +public: + virtual ~BenchMark3d_5() {} + BenchMark3d_5(Field globalShift, Field factor) + : pi2_( 2.0 * M_PI ) + { + if( dim != 3 ) + { + DUNE_THROW(Dune::NotImplemented,"Problem only implemented for dim=3"); + } + + { + Field (&tensor)[dim] = tensor_[ 0 ]; + tensor[0] = 1.0; + tensor[1] = 10.0; + tensor[2] = 0.01; + } + + { + Field (&tensor)[dim] = tensor_[ 1 ]; + tensor[0] = 1.0; + tensor[1] = 0.1; + tensor[2] = 100.0; + } + + { + Field (&tensor)[dim] = tensor_[ 2 ]; + tensor[0] = 1.0; + tensor[1] = 0.01; + tensor[2] = 10.0; + } + + { + Field (&tensor)[dim] = tensor_[ 3 ]; + tensor[0] = 1.0; + tensor[1] = 100.0; + tensor[2] = 0.1; + } + + alpha_[ 0 ] = 0.1; + alpha_[ 1 ] = 10.0; + alpha_[ 2 ] = 100.0; + alpha_[ 3 ] = 0.01; + + for(int i=0; i<numDomain; ++i ) + { + trace_[ i ] = 0; + for( int j=0; j<dim; ++ j) + trace_[ i ] += tensor_[ i ][ j ]; + } + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + const int domain = getDomain( x ); + assert( domain >= 0 && domain < numDomain ); + for(int i=0; i<dim; ++i) + for(int j=0; j<dim; ++j ) + k[i][j] = 0; + // set diagonal + for(int j=0; j<dim; ++j ) + k[j][j] = tensor_[ domain ][ j ]; + } + + int getDomain(const DomainField x[dim]) const + { + if (x[1]<=0.5) + { + if (x[2]<=0.5) return 0; else return 3; + } + else + { + if (x[2]<=0.5) return 1; else return 2; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + const int domain = getDomain(x); + assert( domain >= 0 && domain < numDomain ); + Field result = 4.0*M_PI*M_PI*sin(pi2_*x[0])*sin(pi2_*x[1])*sin(pi2_*x[2]); + result *= alpha_[ domain ] * trace_[ domain ]; + return result; + } + + virtual Field exact(const DomainField x[dim]) const + { + const int domain = getDomain(x); + assert( domain >= 0 && domain < numDomain ); + Field val = sin(pi2_*x[0])*sin(pi2_*x[1])*sin(pi2_*x[2]); + val *= alpha_[ domain ]; + return val ; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + const int domain = getDomain(x); + assert( domain >= 0 && domain < numDomain ); + + const Field x_pi = pi2_*x[0] ; + const Field y_pi = pi2_*x[1] ; + const Field z_pi = pi2_*x[2] ; + + grad[0] = pi2_ * cos( x_pi ) * sin( y_pi ) * sin( z_pi ); + grad[1] = pi2_ * sin( x_pi ) * cos( y_pi ) * sin( z_pi ); + grad[2] = pi2_ * sin( x_pi ) * sin( y_pi ) * cos( z_pi ); + + for(int i=0; i<dim; ++i ) + grad[ i ] *= alpha_[ domain ]; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +#endif diff --git a/dune/fem-dg/test/poisson/benchmark.hh b/dune/fem-dg/test/poisson/benchmark.hh new file mode 100644 index 00000000..73670b2d --- /dev/null +++ b/dune/fem-dg/test/poisson/benchmark.hh @@ -0,0 +1,1118 @@ +#ifndef ELLIPTPROBLEM_CC +#define ELLIPTPROBLEM_CC + +#include <cmath> +#include <set> +#include <cassert> + +template<int dim, class DomainField, class Field> +class DataFunctionIF +{ +protected: + DataFunctionIF() {} +public: + // destructor + virtual ~DataFunctionIF() {} + + // returns true if K is constant on one element + virtual bool constantLocalK () const { return true; } + + // diffusion tensor + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const = 0; + // right hand side + virtual Field rhs (const DomainField x[dim]) const = 0; + // right hand side + virtual Field rhs (const double time, const DomainField x[dim]) const + { + return rhs( x ); + } + virtual void velocity(const DomainField x[dim], DomainField v[dim]) const + { + for(int i=0; i<dim; ++i) + v[i] = 0.; + } + + // exact solution + virtual Field exact(const DomainField x[dim]) const = 0; + + // exact solution (time dependent) + virtual Field exact(const double time, const DomainField x[dim]) const + { + return exact( x ); + } + + // exact gradient + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const = 0; + + // boundary data + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const = 0; + + // neumann boundary + virtual void neumann(const DomainField x[dim], Field grad[dim]) const + { + Field tmp[dim]; + gradExact(x,tmp); + Field k[dim][dim]; + K(x, k); + for(int i=0; i<dim; ++i) + { + grad[i] = 0; + for(int j=0; j<dim; ++j) + grad[i] += tmp[j] * k[i][j]; + } + } + + // boundary data + virtual bool boundaryDataFunction(const double time, + const DomainField x[dim], + Field & val) const + { + return boundaryDataFunction(x, val); + } + + // neumann boundary + virtual void neumann(const double time, + const DomainField x[dim], Field grad[dim]) const + { + return neumann(x, grad); + } + + virtual int getBoundaryId(const DomainField x[dim]) const + { + for(int i=0; i<dim; ++i) + { + const int id = 2 * i; + if( x[i] <= 1e-10 ) + { + return id; + } + else if ( x[i] >= 0.99999999 ) + { + return id + 1; + } + } + + //assert( false ); + //abort(); + return -1; + } + virtual int getBoundaryId(const DomainField x[dim], + const DomainField n[dim]) const + { + return getBoundaryId( x ); + } + + Field SQR( const Field& a ) const + { + return (a * a); + } +}; + +template <int dim, class DomainField, class Field> +class AlbertaProblem : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~AlbertaProblem() {} + AlbertaProblem(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + //assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) k[i][j] = 0; + k[i][i] = factor_; + } + } + + inline Field xSqr(const DomainField x[dim]) const + { + Field xsqr = 0.0; + for(int i=0; i<dim; ++i) xsqr += x[i] * x[i]; + return xsqr; + } + + virtual Field rhs (const DomainField x[dim]) const + { + const Field xsqr = xSqr( x ); + return -(400.0 * xsqr - 20.0 * dim) * std :: exp( -10.0 * xsqr ); + } + + virtual Field exact(const DomainField x[dim]) const + { + return std :: exp( -10.0 * xSqr( x ) ); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + const Field factor = -20.0 * std :: exp( -10.0 * xSqr( x ) ); + for(int i=0; i<dim; ++i) + grad[i] = x[i] * factor ; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + //if(x[0] <= 0.0) return false; + //if(x[1] <= 0.0) return false; + return true; + //return false; + } +}; + + +template <int dim, class DomainField, class Field> +class SinSinSin : public DataFunctionIF<dim,DomainField,Field> +{ + Field K_[dim][dim]; +public: + virtual ~SinSinSin() {} + SinSinSin(Field globalShift, Field factor) + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + if( i == j ) + { + if( i == 0 ) + K_[i][j] = 10.;//factor; + else + K_[i][j] = 0.1;//factor; + } + /* + else if( std::abs( i - j ) == 1 ) + { + K_[i][j] = 0.5; + } + */ + else K_[i][j] = 0; + } + } + + /* + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + std::cout << K_[i][j] << " "; + } + std::cout << std::endl; + } + */ + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) + { + k[i][j] = K_[i][j]; + } + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + Field sum = 0; + int comp[ dim - 1 ] ; + for(int i=0; i<dim; ++i) + { + comp[0] = i; + for(int j=0; j<dim; ++j) + { + comp[ dim - 2 ] = j; + sum += K_[j][i] * laplace( x, comp ); + } + } + return -sum; + } + + virtual Field exact(const DomainField x[dim]) const + { + const Field pi = 2.0 * M_PI; + Field val = 1.0; + for(int i=0; i<dim; ++i) + { + val *= sin( pi * x[i] ); + } + return val; + } + + double laplace(const DomainField x[dim], const int comp[dim - 1] ) const + { + const Field pi = 2.0 * M_PI; + Field val = pi * pi; + + std::set<int> comps ; + for( int j=0; j<dim-1; ++j) + { + comps.insert( comp[j] ); + } + + if( comps.size() == 1 ) + { + // add other components + for(int i=0; i<dim; ++i) + { + val *= sin( pi * x[ i ] ); + } + + // minus because sin'' = -sin + return -val; + } + else + { + for( int i=0; i<dim-1; ++i) + { + val *= cos( pi * x[ comp[i] ] ); + } + + for(int i=0; i<dim; ++i) + { + if( comps.find( i ) == comps.end() ) + val *= sin( pi * x[ i ] ); + } + return val; + } + } + + double gradient(const DomainField x[dim], const int comp) const + { + const Field pi = 2.0 * M_PI; + Field val = pi * cos( pi * x[ comp ] ); + // add other components + for(int j=1; j<dim; ++j) + { + val *= sin( pi * x[ (comp + j) % dim ] ); + } + return val; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + for(int i=0; i<dim; ++i) + { + grad[i] = gradient( x, i ); + } + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + //if(x[0] <= 0.0) return false; + return true; + //return false; + } +}; + + +template <int dim, class DomainField, class Field> +class SinSin : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~SinSin() {} + SinSin(Field globalShift, Field factor) + : globalShift_(globalShift) + , factor_(factor) + { + //assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + Field sin_x = sin(2.0*M_PI*x[0]); + Field sin_y = sin(2.0*M_PI*x[1]); + + Field val = 8.0 * M_PI * M_PI * sin_x * sin_y ; + val *= factor_; + return val; + } + + virtual Field exact(const DomainField x[dim]) const + { + Field val = sin(2.0*M_PI*x[0]) * sin(2.0*M_PI*x[1]); + val += globalShift_; + return val; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 2.0*M_PI*cos(2.0*M_PI*x[0])*sin(2.0*M_PI*x[1]); + grad[1] = 2.0*M_PI*sin(2.0*M_PI*x[0])*cos(2.0*M_PI*x[1]); + + // initial grad with zero for 3d + for( int i=2; i<dim; ++i) grad[i] = 0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + //if(x[0] <= 0.0) return false; + return true; + //return false; + } +}; + +template <int dim, class DomainField, class Field> +class CosCos : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~CosCos() {} + CosCos(Field globalShift, Field factor) + : globalShift_(globalShift) + , factor_(factor) + { + //assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + + virtual Field rhs (const DomainField x[dim]) const + { + Field cos_x = cos(2.0*M_PI*x[0]); + Field cos_y = cos(2.0*M_PI*x[1]); + + Field val = 8.0 * M_PI*M_PI* cos_x * cos_y ; + val *= factor_; + return val; + //return 0; + } + + virtual Field exact(const DomainField x[dim]) const + { + Field val = cos(2.0*M_PI*x[0]) * cos(2.0*M_PI*x[1]); + val += globalShift_; + return val; + //return x[1]; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 2.0*M_PI*-sin(2.0*M_PI*x[0])*cos(2.0*M_PI*x[1]); + grad[1] = 2.0*M_PI*cos(2.0*M_PI*x[0])*-sin(2.0*M_PI*x[1]); + //grad[0] = 0.; + //grad[1] = 1.; + + // initial grad with zero for 3d + for( int i=2; i<dim; ++i) grad[i] = 0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + //if(x[0] <= 0.0) return false; + return true; + } +}; + +//! problem from Castillo paper +template <int dim, class DomainField, class Field> +class CastilloProblem : public DataFunctionIF<dim,DomainField,Field> +{ + using DataFunctionIF<dim,DomainField,Field> :: SQR; + const Field globalShift_; + const Field factor_; +public: + virtual ~CastilloProblem() {} + CastilloProblem(Field globalShift, Field factor) + : globalShift_(globalShift) + , factor_(factor) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + + virtual Field rhs (const DomainField x[dim]) const + { + Field ret = 0.0; + Field tmp =-23+7*SQR(x[1])-24*x[0]+24*x[0]*SQR(x[1])+7*SQR(x[0])+9*SQR(x[0])*SQR(x[1])-24 + *x[1]+24*x[1]*SQR(x[0]); + + ret=-0.5*exp(0.75*(x[0]+x[1])); + ret *= tmp; + ret *= factor_; + return ret; + } + + virtual Field exact(const DomainField x[dim]) const + { + Field val = 4.0 *(1.-SQR(x[0]))*(1.-SQR(x[1]))*exp(0.75*(x[0]+x[1])); + val += globalShift_; + return val; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + // not implemented yet + grad[0] = grad[1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + +//! problem Einstringende Ecke +template <class DomainField, class Field> +class InSpringingCorner2d : public DataFunctionIF<2,DomainField,Field> +{ + enum { dim = 2 }; + const Field globalShift_; + const Field factor_; + const Field lambda_; +public: + virtual ~InSpringingCorner2d() {} + InSpringingCorner2d(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + , lambda_(180./270.) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + double r2 = radius(x[0],x[1]); + double phi = argphi(x[0],x[1]); + return pow(r2,lambda_*0.5)*sin(lambda_*phi); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + double r2=radius(x[0],x[1]); + double phi=argphi(x[0],x[1]); + double r2dx=2.*x[0]; + double r2dy=2.*x[1]; + double phidx=-x[1]/r2; + double phidy=x[0]/r2; + double lambdaPow = (lambda_*0.5)*pow(r2,lambda_*0.5-1.); + grad[0]= lambdaPow * r2dx * sin(lambda_ * phi) + + lambda_ * cos( lambda_ * phi) * phidx * pow(r2,lambda_ * 0.5); + grad[1]= lambdaPow * r2dy * sin(lambda_ * phi) + + lambda_ * cos( lambda_ * phi) * phidy * pow(r2,lambda_*0.5); + assert( grad[0] == grad[0] ); + assert( grad[1] == grad[1] ); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } + + private: + /** \brief proper implementation of atan(x,y) + */ + inline double argphi(double x,double y) const + { + double phi=arg(std::complex<double>(x,y)); + if (y<0) phi+=2.*M_PI; + return phi; + } + + /** \brief implementation for the radius squared + * (^0.5 is part of function implementation) + */ + inline double radius(double x, double y) const + { + double ret =0; + ret = x*x +y*y; + return ret; + } +}; + +//! problem Einstringende Ecke 3d +template <int dim, class DomainField, class Field> +class InSpringingCorner : public DataFunctionIF<dim,DomainField,Field> +{ + typedef InSpringingCorner2d<DomainField, Field> Corner2dType ; + Corner2dType corner2d_; + const Field factor_; + +public: + virtual ~InSpringingCorner() {} + InSpringingCorner(Field globalShift, Field factor) + : corner2d_(globalShift, factor), + factor_( factor ) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + return 0.0; + } + + virtual Field exact(const DomainField x[dim]) const + { + DomainField x2d[ 2 ]; + if ( dim == 2 ) + { + for( int i=0; i<dim; ++i ) x2d[ i ] = x[ i ]; + return corner2d_.exact( x2d ); + } + else + { + double sum = 0; + // ( x, y) + x2d[ 0 ] = -x[ 0 ]; x2d[ 1 ] = x[ 1 ]; + sum += corner2d_.exact( x2d ); + // (-y,-z) + //x2d[ 0 ] = -x[ 2 ]; x2d[ 1 ] = -x[ 1 ]; + x2d[ 0 ] = -x[ 1 ]; x2d[ 1 ] = -x[ 2 ]; + sum += corner2d_.exact( x2d ); + // ( z,-x) + x2d[ 0 ] = -x[ 0 ]; x2d[ 1 ] = -x[ 2 ]; + sum += corner2d_.exact( x2d ); + + //sum *= (x[ 0 ] + 1.0) / 2.0; + return sum ; + } + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + for( int i=0; i<dim; ++i ) grad[ i ] = 0; + if ( dim == 2 ) + { + DomainField x2d[ 2 ]; + for( int i=0; i<dim; ++i ) x2d[ i ] = x[ i ]; + corner2d_.gradExact( x2d, &grad[ 0 ] ); + } + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + +//! problem Einstringende Ecke 3d +template <int dim, class DomainField, class Field> +class FicheraCorner : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; + +public: + virtual ~FicheraCorner() {} + FicheraCorner(Field globalShift, Field factor) + : globalShift_( globalShift ), + factor_( factor ) + { + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + const double u = exact( x ); + return -3.0/(4.0* u * u * u ); + } + + virtual Field exact(const DomainField x[dim]) const + { + double xAbs = 0; + for( int i=0; i<dim; ++i ) + xAbs += x[ i ] * x[ i ]; + return std::pow( xAbs, 0.25 ); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + const double u = exact( x ); + const double u3 = 2.0 * u * u * u ; + for( int i=0; i<dim; ++i ) grad[ i ] = x[ i ] / u3 ; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + +//! problem single Hump +template <int dim, class DomainField, class Field> +class Hump : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~Hump() {} + Hump(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + double w=10.*x[0]*x[0]+10.*x[1]; + double v=(x[0]-x[0]*x[0])*(x[1]-x[1]*x[1]); + double dwx = 20.*x[0]; + double dwy = 10.; + double dwxx = 20.; + double dwyy = 0.; + double dvx = (1.-2.*x[0])*(x[1]-x[1]*x[1]); + double dvy = (1.-2.*x[1])*(x[0]-x[0]*x[0]); + double dvxx = -2.*(x[1]-x[1]*x[1]); + double dvyy = -2.*(x[0]-x[0]*x[0]); + Field grad[dim]; + grad[0] = exp(w)*(dwx*v*v + 2.*v*dvx); + grad[1] = exp(w)*(dwy*v*v + 2.*v*dvy); + double dxx = dwx*grad[0] + exp(w)*(dwxx*v*v+dwx*2.*v*dvx + 2.*dvx*dvx+2.*v*dvxx); + double dyy = dwy*grad[1] + exp(w)*(dwyy*v*v+dwy*2.*v*dvy + 2.*dvy*dvy+2.*v*dvyy); + return -dxx-dyy; + } + + virtual Field exact(const DomainField x[dim]) const + { + double w=10.*x[0]*x[0]+10.*x[1]; + double v=(x[0]-x[0]*x[0])*(x[1]-x[1]*x[1]); + return exp(w)*v*v; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + double w=10.*x[0]*x[0]+10.*x[1]; + double v=(x[0]-x[0]*x[0])*(x[1]-x[1]*x[1]); + double dwx = 20.*x[0]; + double dwy = 10.; + double dvx = (1.-2.*x[0])*(x[1]-x[1]*x[1]); + double dvy = (1.-2.*x[1])*(x[0]-x[0]*x[0]); + grad[0] = exp(w)*(dwx*v*v + 2.*v*dvx); + grad[1] = exp(w)*(dwy*v*v + 2.*v*dvy); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +//! problem Riviere-Bastian +template <int dim, class DomainField, class Field> +class RiviereProblem : public DataFunctionIF<dim,DomainField,Field> +{ + using DataFunctionIF<dim,DomainField,Field> :: SQR; + const Field globalShift_; + const Field factor_; +public: + virtual ~RiviereProblem() {} + RiviereProblem(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField x[dim]) const + { + Field val = exact(x); + Field x_part = val * SQR(-2.0 * (x[0] - 0.5)) - 2.0 * val; + Field y_part = val * SQR(-2.0 * (x[1] - 0.5)) - 2.0 * val; + return -(x_part + y_part); + } + + virtual Field exact(const DomainField x[dim]) const + { + Field power = -( SQR( x[0] - 0.5 ) + SQR( x[1] - 0.5 ) ); + return pow( M_E , power ); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + Field val = exact( x ); + grad[0] = val * ( -2.0*x[0] + 1.0 ); + grad[1] = val * ( -2.0*x[1] + 1.0 ); + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +//! problem Riviere-Bastian +template <int dim, class DomainField, class Field> +class HeatProblem : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~HeatProblem() {} + HeatProblem(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + double scp(const DomainField x[dim]) const + { + double r2 = 0.0; + for(int i=0; i<dim; ++i) r2 += x[i]*x[i]; + return r2; + } + + virtual Field rhs (const DomainField x[dim]) const + { + return rhs(0.0, x); + } + + virtual Field rhs (const double time, const DomainField x[dim]) const + { + double r2 = scp( x ); + + double ux = std::sin(M_PI*time)* std::exp(-10.0*r2); + double ut = M_PI*std::cos(M_PI*time)*std::exp(-10.0*r2); + return(ut - (400.0*r2 - 20.0*dim)*ux); + } + + virtual Field exact(const DomainField x[dim]) const + { + return exact(0.0, x); + } + + virtual Field exact(const double time, const DomainField x[dim]) const + { + double r2 = scp( x ); + return(std::sin( M_PI * time) * std::exp( -10.0 * r2)); + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = grad[1] = 0.0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + assert( false ); + val = exact( x ); + return true; + } + + virtual bool boundaryDataFunction(const double time, + const DomainField x[dim], + Field & val) const + { + val = exact( time, x ); + return true; + } +}; + +template <int dim, class DomainField, class Field> +class BoundaryLayerProblem : public DataFunctionIF<dim,DomainField,Field> +{ +public: + virtual ~BoundaryLayerProblem() {} + BoundaryLayerProblem(Field globalShift, Field factor) + : eps_(factor) + { + assert( eps_ > 0 ); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + for(int j=0; j<dim; ++j) k[i][j] = 0; + k[i][i] = 1.; // eps_; + } + } + + void velocity(const DomainField x[dim], DomainField v[dim]) const + { + for(int i=0; i<dim; ++i) + v[i] = 1./eps_; + } + + virtual Field rhs (const DomainField x[dim]) const + { + return 0; + } + + virtual Field exact(const DomainField x[dim]) const + { + Field ret = 1; + for (int i=0;i<dim;++i) + ret *= u1( x[i] ); + return ret; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + for (int i=0;i<dim;++i) + { + grad[ i ] = 1.; + for (int j=0;j<dim;++j) + grad[ i ] *= (j==i)? du1( x[i] ):u1( x[i] ); + } + return; + } + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +private: + double u1(double x) const + { + return (exp(x/eps_)-1.) / (exp(1./eps_)-1.); + } + double du1(double x) const + { + return (exp(x/eps_)/eps_) / (exp(1./eps_)-1.); + } + const double eps_; +}; + + +//! problem CurvedRidges (deal.II step-14) +template <int dim, class DomainField, class Field> +class CurvedRidges : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; +public: + virtual ~CurvedRidges() {} + CurvedRidges(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField p[dim]) const + { + double q = p[ 0 ]; + for (unsigned int i=1; i<dim; ++i) + { + q += std::sin(10*p[ i ]+5*p[ 0 ]*p[ 0 ]); + } + const double u = std::exp(q); + double t1 = 1, t2 = 0, t3 = 0; + for (unsigned int i=1; i<dim; ++i) + { + t1 += std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) * 10 * p[ 0 ]; + t2 += 10*std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) - + 100*std::sin(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) * p[ 0 ]*p[ 0 ]; + t3 += 100*std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ])*std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) - + 100*std::sin(10*p[ i ]+5*p[ 0 ]*p[ 0 ]); + } + t1 = t1*t1; + + return -u*(t1+t2+t3); + } + + virtual Field exact(const DomainField p[dim]) const + { + double q = p[ 0 ]; + for (unsigned int i=1; i<dim; ++i) + { + q += std::sin(10*p[ i ]+5*p[ 0 ]*p[ 0 ]); + } + const double exponential = std::exp(q); + return exponential; + } + + virtual void gradExact(const DomainField p[dim], Field grad[dim] ) const + { + double u = exact(p); + grad[0] = 1.; + for (unsigned int i=1; i<dim; ++i) + grad[0] += std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) * 10. * p[0]; + grad[0] *= u; + for (int i=1;i<dim;++i) + { + grad[i] = std::cos(10*p[ i ]+5*p[ 0 ]*p[ 0 ]) * 10.; + grad[i] *= u; + } + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + +//! problem CurvedRidges (deal.II step-14) +template <int dim, class DomainField, class Field> +class Excercise2_3 : public DataFunctionIF<dim,DomainField,Field> +{ + const Field globalShift_; + const Field factor_; + Field point_ [ dim ]; +public: + virtual ~Excercise2_3() {} + Excercise2_3(Field globalShift, Field factor) + : globalShift_(0.0) + , factor_(1.0) + { + for(int i=0; i<dim; ++i) point_[ i ] = 0.75; + assert(dim == 2); + } + + virtual void K(const DomainField x[dim], Field k[dim][dim] ) const + { + for(int i=0; i<dim; ++i) + { + k[i][i] = factor_; + for(int j=0; j<i; ++j) k[i][j] = 0; + for(int j=i+1; j<dim; ++j) k[i][j] = 0; + } + } + + virtual Field rhs (const DomainField p[dim]) const + { + return 1.0; + } + + virtual Field exact(const DomainField p[dim]) const + { + // exact solution not known + return 0.0; + } + + virtual void gradExact(const DomainField x[dim], Field grad[dim] ) const + { + grad[0] = 0; + grad[1] = 0; + } + + virtual bool boundaryDataFunction(const DomainField x[dim], Field & val) const + { + val = exact( x ); + return true; + } +}; + + + + +#include "benchmark.cc" +#endif diff --git a/dune/fem-dg/test/poisson/benchmarkproblem.hh b/dune/fem-dg/test/poisson/benchmarkproblem.hh new file mode 100644 index 00000000..ff3960f4 --- /dev/null +++ b/dune/fem-dg/test/poisson/benchmarkproblem.hh @@ -0,0 +1,266 @@ +#ifndef DUNE_BENCHMARK_PROBLEM_HH +#define DUNE_BENCHMARK_PROBLEM_HH + +#include <dune/fem/io/parameter.hh> +#include <dune/fem/space/common/functionspace.hh> + +// local includes +#include "../common/probleminterfaces.hh" +#include "benchmark.hh" + + +namespace Dune { + +template <class GridType> /*@LST0S@*/ +struct BenchmarkProblems : public ProblemInterface< + Dune :: Fem :: FunctionSpace< double, double, GridType::dimension, DIMRANGE> > +{ /*@LST0E@*/ +public: + typedef ProblemInterface< + Dune :: Fem::FunctionSpace< double, double, + GridType::dimension, DIMRANGE > + > BaseType; + + enum{ dimDomain = BaseType :: dimDomain }; + enum{ dim = dimDomain }; + typedef typename BaseType :: DomainType DomainType; + typedef typename BaseType :: RangeType RangeType; + typedef typename BaseType :: JacobianRangeType JacobianRangeType; + typedef typename BaseType :: DiffusionMatrixType DiffusionMatrixType; + typedef typename GridType :: ctype FieldType ; + + typedef DataFunctionIF< dimDomain, FieldType, FieldType > DataFunctionType; + + /** + * @brief define problem parameters + */ + BenchmarkProblems (const int problemNumber) : + BaseType (), + data_(0) + { + FieldType shift = Dune :: Fem::Parameter :: getValue< double > ("femhowto.globalshift", 0); + FieldType factor = Dune :: Fem::Parameter :: getValue< double > ("femhowto.factor", 1); + if( problemNumber == 0 ) + { + data_ = new BenchMark_1<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 1 ) + { + data_ = new BenchMark_1_2<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 2 ) + { + data_ = new BenchMark_2<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 3 ) + { + data_ = new BenchMark_3<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 4 ) + { + data_ = new BenchMark_4<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 5 ) + { + data_ = new BenchMark_5<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 6 ) + { + data_ = new BenchMark_6<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 7 ) + { + data_ = new BenchMark_7<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 8 ) + { + //DUNE_THROW(InvalidStateException,"Problem 8 not available"); + data_ = new CurvedRidges< dim, FieldType,FieldType> (shift,factor); + } + if( problemNumber == 9 ) + { + data_ = new BenchMark_9<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 10 ) + { + data_ = new SinSin<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 11 ) + { + data_ = new Excercise2_3< dim, FieldType,FieldType> (shift,factor); + } + if( problemNumber == 12 ) + { + data_ = new CastilloProblem<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 13 ) + { + data_ = new InSpringingCorner<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 14 ) + { + data_ = new RiviereProblem<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 15 ) + { + data_ = new HeatProblem<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 16 ) + { + data_ = new AlbertaProblem<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 17 ) + { + data_ = new SinSin<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 18 ) + { + data_ = new CosCos<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 19 ) + { + data_ = new SinSinSin<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 20 ) + { + data_ = new Hump<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 21 ) + { + data_ = new BenchMark3d_1<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 23 ) + { + data_ = new BenchMark3d_3<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 24 ) + { + data_ = new BenchMark3d_4<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 25 ) + { + data_ = new BenchMark3d_5<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 31 ) + { + data_ = new BoundaryLayerProblem<dim,FieldType,FieldType> (shift,factor); + } + if( problemNumber == 32 ) + { + data_ = new FicheraCorner<dim,FieldType,FieldType> (shift,factor); + } + + if( data_ == 0 ) + { + std::cerr << "ERROR: wrong problem number " << std::endl; + abort(); + } + + myName = "Poisson Eqn."; + } + + const DataFunctionType& data() const { assert( data_ ); return *data_; } + + //! this problem has no source term + bool hasStiffSource() const { return true; } + bool hasNonStiffSource() const { return false; } + + void f(const DomainType& arg, + RangeType& res) const + { + res = data().rhs( &arg[ 0 ] ); + } + + double stiffSource(const DomainType& arg, + const double t, + const RangeType& u, + RangeType& res) const + { + res = data().rhs( &arg[ 0 ] ); + return 0; + } + + double nonStiffSource(const DomainType& arg, + const double t, + const RangeType& u, + RangeType& res) const + { + abort(); + return 0.0; + } + + //! return start time + double startTime() const { return 0; } + + bool constantK() const { return data().constantLocalK(); } + + void K(const DomainType& x, DiffusionMatrixType& m) const + { + double k[ dimDomain ][ dimDomain ]; + data().K( &x[0], k ); + + for(int i=0; i<dimDomain; ++i) + for(int j=0; j<dimDomain; ++j) + m[i][j] = k[i][j]; + } + + /** + * @brief getter for the velocity + */ + void velocity(const DomainType& x, DomainType& v) const + { + double vv[ dimDomain ]; + data().velocity( &x[0], vv ); + for (int i=0;i<dimDomain; ++i) + v[i] = vv[i]; + } + + void u(const DomainType& arg, RangeType& res) const /*@LST0S@@LST0E@*/ + { + evaluate(arg, res ); + } + + /** + * @brief evaluates \f$ u_0(x) \f$ + */ + void evaluate(const DomainType& arg, RangeType& res) const /*@LST0S@@LST0E@*/ + { + evaluate(arg, 0, res); + } + + /** + * @brief evaluate exact solution + */ + void evaluate(const DomainType& arg, const double t, RangeType& res) const /*@LST0S@@LST0E@*/ + { + res = data().exact( &arg[ 0 ] ); + } + + void gradient(const DomainType& x, + JacobianRangeType& grad) const + { + for (int i=0;i<RangeType::dimension;++i) + data().gradExact( &x[ 0 ], &grad[ i ][ 0 ] ); + } + + /** + * @brief latex output for EocOutput + */ + std::string description() const + { + std::ostringstream ofs; + + ofs << "Problem: " << myName ; + ofs << ", End time: " << Dune:: Fem :: Parameter::getValue<double>("femhowto.endTime"); + + return ofs.str(); + } + +protected: + DataFunctionType* data_; + std::string myName; +}; + +} +#endif /*DUNE_PROBLEM_HH__*/ + diff --git a/dune/fem-dg/test/poisson/models.hh b/dune/fem-dg/test/poisson/models.hh new file mode 100644 index 00000000..d290b5ae --- /dev/null +++ b/dune/fem-dg/test/poisson/models.hh @@ -0,0 +1,500 @@ +#ifndef POIS_MODELS_HH +#define POIS_MODELS_HH + +#include <dune/fem/version.hh> +#include <dune/fem/misc/fmatrixconverter.hh> +#include <dune/fem/io/parameter.hh> + +#if HAVE_UGGRID +#include <dune/grid/uggrid.hh> +#endif + +namespace Dune +{ +template <class ModelType> +class UpwindFlux; +} + +/********************************************** + * Analytical model * + *********************************************/ +/** + * @brief Traits class for PoissonModel + */ +template <class GridPart,int dimRange2, + int dimRange1=dimRange2* GridPart::GridType::dimensionworld> +class PoissonModelTraits +{ +public: + typedef GridPart GridPartType; + typedef typename GridPartType :: GridType GridType; + static const int dimDomain = GridType::dimensionworld; + static const int dimRange = dimRange2; + static const int dimGradRange = dimRange1; + // Definition of domain and range types + typedef Dune::FieldVector< double, dimDomain > DomainType; + typedef Dune::FieldVector< double, dimDomain-1 > FaceDomainType; + typedef Dune::FieldVector< double, dimRange > RangeType; + typedef Dune::FieldVector< double, dimGradRange > GradientType; + // ATTENTION: These are matrices (c.f. PoissonModel) + typedef Dune::FieldMatrix< double, dimRange, dimDomain > FluxRangeType; + typedef Dune::FieldMatrix< double, dimRange, dimDomain > JacobianRangeType; + typedef Dune::FieldMatrix< double, dimGradRange, dimDomain > DiffusionRangeType; + typedef typename GridType :: template Codim< 0 > :: Entity EntityType; + typedef typename GridPartType :: IntersectionIteratorType IntersectionIterator; + typedef typename IntersectionIterator :: Intersection IntersectionType; + +}; + +/** + * @brief describes the analytical model + * + * This is an description class for the problem + * \f{eqnarray*}{ V + \nabla a(U) & = & 0 \\ + * \partial_t U + \nabla (F(U)+A(U,V)) & = & 0 \\ + * U & = & g_D \\ + * \nabla U \cdot n & = & g_N \f} + * + * where each class methods describes an analytical function. + * <ul> + * <li> \f$F\f$: advection() </li> + * <li> \f$a\f$: diffusion1() </li> + * <li> \f$A\f$: diffusion2() </li> + * <li> \f$g_D\f$ boundaryValue() </li> + * <li> \f$g_N\f$ boundaryFlux1(), boundaryFlux2() </li> + * </ul> + * + * \attention \f$F(U)\f$ and \f$A(U,V)\f$ are matrix valued, and therefore the + * divergence is defined as + * + * \f[ \Delta M = \nabla \cdot (\nabla \cdot (M_{i\cdot})^t)_{i\in 1\dots n} \f] + * + * for a matrix \f$M\in \mathbf{M}^{n\times m}\f$. + * + * @param GridPart GridPart for extraction of dimension + * @param ProblemType Class describing the initial(t=0) and exact solution + */ + + +//////////////////////////////////////////////////////// +// +// Analytical model for the Heat Equation +// dx(u) + div(uV) - epsilon*lap(u)) = 0 +// where V is constant vector +// +//////////////////////////////////////////////////////// +template <class GridPartType,class ProblemImp> +class PoissonModel +{ +public: + typedef ProblemImp ProblemType ; + + typedef typename GridPartType :: GridType GridType; + static const int dimDomain = GridType::dimensionworld; + static const int dimRange = DIMRANGE; + typedef PoissonModelTraits< GridPartType, dimRange, + dimRange*dimDomain > Traits; + typedef typename Traits :: DomainType DomainType; + typedef typename Traits :: RangeType RangeType; + typedef typename Traits :: GradientType GradientType; + typedef typename Traits :: FluxRangeType FluxRangeType; + typedef typename Traits :: DiffusionRangeType DiffusionRangeType; + typedef typename Traits :: FaceDomainType FaceDomainType; + typedef typename Traits :: JacobianRangeType JacobianRangeType; + + typedef typename ProblemType :: DiffusionMatrixType DiffusionMatrixType ; + + typedef typename Traits :: EntityType EntityType; + typedef typename Traits :: IntersectionType IntersectionType; + +public: + static const int ConstantVelocity = false; + /** + * @brief Constructor + * + * initializes model parameter + * + * @param problem Class describing the initial(t=0) and exact solution + */ + PoissonModel(const ProblemType& problem) : problem_(problem) + { + } + + inline bool hasFlux() const { return true ; } + + inline bool hasStiffSource() const { return true ; } + inline bool hasNonStiffSource() const { return false ; } + + inline double nonStiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const GradientType& du, + RangeType & s) const + { + return nonStiffSource( en, time, x, u, s ); + } + + inline double nonStiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const JacobianRangeType& jac, + RangeType & s) const + { + return nonStiffSource( en, time, x, u, s ); + } + + inline double nonStiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + RangeType & s) const + { + abort(); + DomainType xgl = en.geometry().global( x ); + problem_.f( xgl, s ); + return 0; + } + + inline double stiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const GradientType& du, + RangeType & s) const + { + return stiffSource( en, time, x, u, s ); + } + + + inline double stiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const JacobianRangeType& jac, + RangeType & s) const + { + return stiffSource( en, time, x, u, s ); + } + + inline double stiffSource( const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + RangeType & s) const + { + DomainType xgl = en.geometry().global( x ); + problem_.f( xgl, s ); + return 0; + } + + /** + * @brief advection term \f$F\f$ + * + * @param en entity on which to evaluate the advection term + * @param time current time of TimeProvider + * @param x coordinate local to entity + * @param u \f$U\f$ + * @param f \f$f(U)\f$ + */ + inline void advection(const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + FluxRangeType & f) const + { + // evaluate velocity V + DomainType v; + velocity( en, time, x, v ); + + //f = uV; + for( int r=0; r<dimRange; ++r ) + for( int d=0; d<dimDomain; ++d ) + f[r][d] = v[ d ] * u[ r ]; + } + + bool hasDirichletBoundary () const + { + return true ; + } + + bool isDirichletPoint( const DomainType& global ) const + { + return true ; + } + +protected: + + /** + * @brief velocity calculation, is called by advection() + */ + inline void velocity(const EntityType& en, + const double time, + const DomainType& x, + DomainType& v) const + { + problem_.velocity(en.geometry().global(x), v); + } + +public: + + /** + * @brief diffusion term \f$a\f$ + */ + inline void jacobian(const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + DiffusionRangeType& a) const + { + a = 0; + + assert( a.rows == dimRange * dimDomain ); + assert( a.cols == dimDomain ); + + for (int r=0;r<dimRange;r++) + for (int d=0;d<dimDomain;d++) + a[dimDomain*r+d][d] = u[r]; + } + + template <class T> + T SQR( const T& a ) const + { + return (a * a); + } + + inline void eigenValues(const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + RangeType& maxValue) const + { + DiffusionMatrixType K ; + DomainType xgl = en.geometry().global( x ); + problem_.K( xgl, K ); + + DomainType values ; + // calculate eigenvalues + Dune::FMatrixHelp :: eigenValues( K, values ); + + maxValue = SQR(values[ dimDomain -1 ]) /values[0]; + return ; + + // take max eigenvalue + maxValue = values.infinity_norm(); + } + + inline double lambdaK( const DiffusionMatrixType& K ) const + { + DomainType values ; + // calculate eigenvalues + Dune::FMatrixHelp :: eigenValues( K, values ); + + // value[ 0 ] is smallest ev + return SQR(values[ dimDomain -1 ]) / values[ 0 ]; + } + + inline double penaltyFactor( const EntityType& inside, + const EntityType& outside, + const double time, + const DomainType& xInside, + const RangeType& uLeft, + const RangeType& uRight ) const + { + DiffusionMatrixType K ; + double betaK, betaInside, betaOutside ; + if( problem_.constantK() ) + { + DiffusionMatrixType Kinside ; + DiffusionMatrixType Koutside; + + const DomainType xglIn = inside.geometry().center(); + problem_.K( xglIn , Kinside ); + const DomainType xglOut = outside.geometry().center(); + problem_.K( xglOut , Koutside ); + + K = Kinside ; + K += Koutside ; + K *= 0.5 ; + + betaInside = lambdaK( Kinside ); + betaOutside = lambdaK( Koutside ); + + betaK = lambdaK( K ); + } + else + { + const DomainType xgl = inside.geometry().global( xInside ); + problem_.K( xgl , K ); + + betaK = lambdaK( K ); + betaInside = betaOutside = betaK; + } + + const double jump = std::tanh( std::abs( betaInside - betaOutside ) ); + + // only for small values of betS apply betS in smooth cases + const double betaN = std :: min( betaK , 1.0 ); + + // betS becomes 1 if the eigen values of both matrices are the same + betaK = betaK * jump + (1.0 - jump) * betaN; + + return betaK ; + } + + inline double penaltyBoundary( const EntityType& inside, + const double time, + const DomainType& xInside, + const RangeType& uLeft ) const + { + return penaltyFactor( inside, inside, time, xInside, uLeft, uLeft ); + } + + /** + * @brief diffusion term \f$A\f$ + */ + template <class JacobianType> + inline void diffusion(const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const JacobianType& jac, + FluxRangeType& A) const + { + // for constant K evalute at center (see Problem 4) + const DomainType xgl = ( problem_.constantK() ) ? + en.geometry().center () : en.geometry().global( x ) ; + + DiffusionMatrixType K ; + + // fill diffusion matrix + problem_.K( xgl, K ); + + // apply diffusion + for( int r =0; r<dimRange; ++r ) + K.mv( jac[ r ] , A[ r ] ); + } + + inline void diffusion(const EntityType& en, + const double time, + const DomainType& x, + const RangeType& u, + const GradientType& vecJac, + FluxRangeType& A) const + { + Dune :: Fem :: FieldMatrixConverter< GradientType, FluxRangeType> jac( vecJac ); + diffusion( en, time, x, u, jac, A ); + } + + inline double diffusionTimeStep( const IntersectionType &it, + const double enVolume, + const double circumEstimate, + const double time, + const FaceDomainType& x, + const RangeType& u ) const + { + return 0; + } + +public: + /** + * @brief checks for existence of dirichlet boundary values + */ + inline bool hasBoundaryValue(const IntersectionType& it, + const double time, + const FaceDomainType& x) const + { + return true; + } + + /** + * @brief neuman boundary values \f$g_N\f$ for pass2 + */ + inline double boundaryFlux(const IntersectionType& it, + const double time, + const FaceDomainType& x, + const RangeType& uLeft, + const GradientType& vLeft, + RangeType& gLeft) const + { + gLeft = 0.; + return 0.; + } + + /** + * @brief neuman boundary values \f$g_N\f$ for pass1 + */ + inline double boundaryFlux(const IntersectionType& it, + const double time, + const FaceDomainType& x, + const RangeType& uLeft, + RangeType& gLeft) const + { + gLeft = 0.; + return 0.; + } + + /** + * @brief diffusion boundary flux + */ + inline double diffusionBoundaryFlux( const IntersectionType& it, + const double time, + const FaceDomainType& x, + const RangeType& uLeft, + const GradientType& gradLeft, + RangeType& gLeft ) const + { + Dune :: Fem :: FieldMatrixConverter< GradientType, JacobianRangeType> jacLeft( gradLeft ); + return diffusionBoundaryFlux( it, time, x, uLeft, jacLeft, gLeft ); + } + + /** \brief boundary flux for the diffusion part + */ + template <class JacobianRangeImp> + inline double diffusionBoundaryFlux( const IntersectionType& it, + const double time, + const FaceDomainType& x, + const RangeType& uLeft, + const JacobianRangeImp& jacLeft, + RangeType& gLeft ) const + { + std::cerr <<"diffusionBoundaryFlux shouldn't be used in this model" <<std::endl; + abort(); + } + + + + /** + * @brief dirichlet boundary values + */ + inline void boundaryValue(const IntersectionType& it, + const double time, + const FaceDomainType& x, + const RangeType& uLeft, + RangeType& uRight) const + { + if (it.boundaryId() == 99) // Dirichlet zero boundary conditions + { + uRight = 0; + } + else + { + DomainType xgl = it.geometry().global( x ); + problem_.g(xgl, uRight); + } + } + inline void boundaryValue(const DomainType& xgl, + RangeType& uRight) const + { + problem_.g(xgl, uRight); + } + + const ProblemType& problem () const { return problem_; } + + protected: + const ProblemType& problem_; + friend class Dune::UpwindFlux<PoissonModel>; +}; + +#endif diff --git a/dune/fem-dg/test/poisson/passtraits.hh b/dune/fem-dg/test/poisson/passtraits.hh new file mode 100644 index 00000000..1a135782 --- /dev/null +++ b/dune/fem-dg/test/poisson/passtraits.hh @@ -0,0 +1,105 @@ +#ifndef DUNE_FEM_DG_PASSTRAITS_HH +#define DUNE_FEM_DG_PASSTRAITS_HH + +// Dune includes +#include <dune/fem/gridpart/adaptiveleafgridpart.hh> + +// Dune-Fem includes +#include <dune/fem/space/finitevolume.hh> +#include <dune/fem/space/discontinuousgalerkin.hh> +#include <dune/fem/space/lagrange.hh> +#include <dune/fem/space/padaptivespace.hh> +#include <dune/fem/pass/localdg/discretemodel.hh> +#include <dune/fem/function/adaptivefunction.hh> +#include <dune/fem/quadrature/cachingquadrature.hh> +#include <dune/fem-dg/operator/adaptation/adaptation.hh> +#include <dune/fem/function/blockvectorfunction.hh> + +#if HAVE_PETSC +#include <dune/fem/function/petscdiscretefunction.hh> +#endif + + +namespace Dune { + + //PassTraits + //---------- + + template <class Model,int dimRange,int polOrd> + class PassTraits + { + public: + typedef typename Model :: Traits ModelTraits; + typedef typename ModelTraits :: GridPartType GridPartType; + typedef typename GridPartType :: GridType GridType; + typedef typename GridType :: ctype ctype; + static const int dimDomain = Model :: Traits :: dimDomain; + + template <class Grid, int dim > + struct FaceQuadChooser + { + typedef Dune::Fem::CachingQuadrature< GridPartType, 1 > Type; + }; + +#if HAVE_UG + template <int dim> + struct FaceQuadChooser< const Dune::UGGrid< dim >, dim > + { + typedef Dune::Fem::ElementQuadrature< GridPartType, 1 > Type; + }; +#endif + + // CACHING + typedef typename FaceQuadChooser< const GridType, GridType::dimension > :: Type FaceQuadratureType; + typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > VolumeQuadratureType; + + // Allow generalization to systems + typedef Dune::Fem::FunctionSpace< ctype, double, dimDomain, dimRange > FunctionSpaceType; +#if DGSCHEME +#if ONB + #warning using DG space with ONB + typedef Dune::Fem::DiscontinuousGalerkinSpace +#elif LAG + #warning using DG space with Lagrange base functions + typedef Dune::Fem::LagrangeDiscontinuousGalerkinSpace +#elif LEG + #warning using DG space with hierarich Legendre base functions + typedef Dune::Fem::HierarchicLegendreDiscontinuousGalerkinSpace +#else +#define USE_STRONG_BC + #warning using p-adaptive DG space + typedef Dune::Fem::PAdaptiveDGSpace +#define PADAPTSPACE +#endif +#else +#define USE_STRONG_BC +#if LAGRANGESPACE + #warning using Lagrange space + typedef Dune::Fem::LagrangeDiscreteFunctionSpace +#else +#define USE_STRONG_BC + #warning using p-adaptive Lagrange space + typedef Dune::Fem::PAdaptiveLagrangeSpace +#define PADAPTSPACE +#endif +#endif + < FunctionSpaceType, GridPartType, polOrd, Dune::Fem::CachingStorage > DiscreteFunctionSpaceType; + +#if WANT_ISTL + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction< DiscreteFunctionSpaceType > DestinationType; +#elif WANT_PETSC + typedef Dune::Fem::PetscDiscreteFunction< DiscreteFunctionSpaceType > DestinationType; +#else + typedef Dune::Fem::AdaptiveDiscreteFunction< DiscreteFunctionSpaceType > DestinationType; +#endif + + // Indicator for Limiter + typedef Dune::Fem::FunctionSpace< ctype, double, dimDomain, 3> FVFunctionSpaceType; + typedef Dune::Fem::FiniteVolumeSpace<FVFunctionSpaceType,GridPartType, 0, Dune::Fem::SimpleStorage> IndicatorSpaceType; + typedef Dune::Fem::AdaptiveDiscreteFunction<IndicatorSpaceType> IndicatorType; + + typedef AdaptationHandler< GridType, FunctionSpaceType > AdaptationHandlerType ; + }; + +} // end namespace Dune +#endif diff --git a/dune/fem-dg/test/poisson/problemcreator.hh b/dune/fem-dg/test/poisson/problemcreator.hh new file mode 100644 index 00000000..62be0b01 --- /dev/null +++ b/dune/fem-dg/test/poisson/problemcreator.hh @@ -0,0 +1,197 @@ +#undef ENABLE_MPI + +#ifndef FEMHOWTO_POISSONSTEPPER_HH +#define FEMHOWTO_POISSONSTEPPER_HH +#include <config.h> + +#include <dune/fem/main/codegen.hh> +#include "passtraits.hh" + +// dune-grid includes +#include <dune/grid/io/file/dgfparser/dgfparser.hh> + +// dune-fem includes +#include <dune/fem/io/parameter.hh> + +// dune-fem-dg includes +#include <dune/fem-dg/operator/fluxes/diffusionflux.hh> + + +#include <dune/fem-dg/operator/dg/dgoperatorchoice.hh> +#include <dune/fem-dg/assemble/primalmatrix.hh> +#include "../common/inverseop.hh" + +// local includes +#include "benchmarkproblem.hh" +#include "models.hh" +#include "estimator1.hh" + +#define NS_ELLIPTIC_OPERATOR +#ifndef TESTOPERATOR +#define TESTOPERATOR +#endif + +template <class GridType> +struct ProblemGenerator +{ + typedef Dune :: ProblemInterface< + Dune::Fem::FunctionSpace< double, double, GridType::dimension, DIMRANGE> > ProblemType; + + template <class GridPart> + struct Traits + { + typedef ProblemType InitialDataType; + typedef PoissonModel< GridPart, InitialDataType > ModelType; + typedef Dune::NoFlux< ModelType > FluxType; + // choice of diffusion flux (see diffusionflux.hh for methods) + static const Dune :: DGDiffusionFluxIdentifier PrimalDiffusionFluxId + = Dune :: method_general ; + }; + + + static inline std::string diffusionFluxName() + { +#if (defined PRIMALDG) + return Dune::Fem::Parameter::getValue< std::string >("dgdiffusionflux.method"); +#else + return "LDG"; +#endif + } + + static inline Dune::GridPtr<GridType> initializeGrid(const std::string description) + { + // use default implementation + //GridPtr<GridType> gridptr = initialize< GridType >( description ); + std::string filename = Dune::Fem::Parameter::getValue< std::string >(Dune::Fem::IOInterface::defaultGridKey(GridType :: dimension, false)); + + // initialize grid + Dune::GridPtr< GridType > gridptr = initialize< GridType >( description ); + + std::string::size_type position = std::string::npos; + if( GridType::dimension == 2) + position = filename.find("mesh3"); + if( GridType::dimension == 3 ) + position = filename.find("_locraf.msh" ); + + std::string::size_type locraf = filename.find("locrafgrid_"); + + std::string::size_type checkerboard = filename.find("heckerboard" );; + + GridType& grid = *gridptr ; + + const int refineelement = 1 ; + + bool nonConformOrigin = Dune::Fem::Parameter::getValue< bool > ( "poisson.nonConformOrigin",false ); + + if ( nonConformOrigin ) + { + std::cout << "Create local refined grid" << std::endl; + if( grid.comm().rank() == 0) + { + typedef typename GridType:: template Codim<0>::LeafIterator IteratorType; + IteratorType endit = grid.template leafend<0>(); + for(IteratorType it = grid.template leafbegin<0>(); it != endit ; ++it) + { + const typename IteratorType :: Entity & entity = *it ; + const typename IteratorType :: Entity :: Geometry& geo = entity.geometry(); + if (geo.center().two_norm() < 0.5) + grid.mark(refineelement, entity ); + } + } + } + else if ( position != std::string::npos || + locraf != std::string::npos ) + { + std::cout << "Create local refined grid" << std::endl; + if( grid.comm().rank() == 0) + { + typedef typename GridType:: template Codim<0>::LeafIterator IteratorType; + Dune::FieldVector<double,GridType::dimension> point(1.0); + if( locraf != std::string::npos ) point[ 0 ] = 3.0; + const int loops = ( GridType::dimension == 2 ) ? 2 : 1; + for (int i=0; i < loops; ++i) + { + point /= 2.0 ; + + IteratorType endit = grid.template leafend<0>(); + for(IteratorType it = grid.template leafbegin<0>(); it != endit ; ++it) + { + const typename IteratorType :: Entity & entity = *it ; + const typename IteratorType :: Entity :: Geometry& geo = entity.geometry(); + bool inside = true ; + const int corners = geo.corners(); + for( int c = 0; c<corners; ++ c) + { + for( int i = 0; i<GridType::dimension; ++i ) + { + if( geo.corner( c )[ i ] - point[ i ] > 1e-8 ) + { + inside = false ; + break ; + } + } + } + if( inside ) grid.mark(refineelement, entity ); + } + } + } + } + else if ( checkerboard != std::string::npos ) + { + std::cout << "Create Checkerboard mesh" << std::endl; + int moduloNum = 32 ; + for( int i = 2; i<32; i *= 2 ) + { + std::stringstream key; + key << i << "x" << i << "x" << i; + std::string::size_type counter = filename.find( key.str() ); + if( counter != std::string::npos ) + { + moduloNum = i; + break ; + } + } + + std::cout << "Found checkerboard cell number " << moduloNum << std::endl; + + if( grid.comm().rank() == 0) + { + typedef typename GridType:: template Codim<0>::LeafIterator IteratorType; + IteratorType endit = grid.template leafend<0>(); + int count = 1; + int modul = 1; // start with 1, such that the fine cube is at (0,0,0) + for(IteratorType it = grid.template leafbegin<0>(); it != endit ; ++it, ++ count ) + { + const typename IteratorType :: Entity & entity = *it ; + if( count % 2 == modul ) + grid.mark(refineelement, entity ); + + if( count % moduloNum == 0 ) + modul = 1 - modul ; + + if( count % (moduloNum * moduloNum) == 0 ) + modul = 1 - modul ; + } + } + } + + // adapt the grid + grid.preAdapt(); + grid.adapt(); + grid.postAdapt(); + + //Dune :: GrapeGridDisplay< GridType > grape( grid ); + //grape.display (); + + return gridptr ; + } + + static ProblemType* problem() + { + // choice of benchmark problem + int probNr = Dune::Fem::Parameter::getValue< int > ( "femhowto.problem" ); + return new Dune :: BenchmarkProblems< GridType > ( probNr ); + } +}; + +#endif // FEMHOWTO_POISSONSTEPPER_HH -- GitLab