Ejemplo n.º 1
0
    def pointSample(self, x0):
        from dune.generator import algorithm, path
        from dune.common import FieldVector
        import numpy
        x0 = FieldVector(x0)
        if self.pointSampler is None:
            import io
            _pointSampleCode = \
            """
            #ifndef FEMPY_UTILITY_HH
            #define FEMPY_UTILITY_HH
            #include <dune/fem/misc/linesegmentsampler.hh>
            #include <dune/fem/gridpart/common/entitysearch.hh>
            #include <dune/fem/function/localfunction/const.hh>

            template <class GF, class DT>
            typename GF::RangeType sample(const GF &gf, DT &point)
            {
              typedef typename GF::DiscreteFunctionSpaceType::GridPartType GridPartType;
              Dune::Fem::EntitySearch<GridPartType> search(gf.space().gridPart());
              const auto &entity = search(point);
              const auto localPoint = entity.geometry().local(point);
              return constLocalFunction(gf,entity).evaluate(localPoint);
            }
            #endif // FEMPY_UTILITY_HH

            """
            self.pointSampler = algorithm.load('sample',
                                               io.StringIO(_pointSampleCode),
                                               self.gridFunction, x0)

        v = self.pointSampler(self.gridFunction, x0)
        return v
Ejemplo n.º 2
0
    def lineSample(self, x0, x1, N):
        from dune.generator import algorithm, path
        from dune.common import FieldVector
        import numpy
        x0, x1 = FieldVector(x0), FieldVector(x1)
        if self.lineSampler is None:
            import io
            _lineSampleCode = \
            """
            #ifndef FEMPY_UTILITY_HH
            #define FEMPY_UTILITY_HH
            #include <vector>
            #include <utility>
            #include <dune/fem/misc/linesegmentsampler.hh>
            #include <dune/fem/gridpart/common/entitysearch.hh>
            #include <dune/fem/function/localfunction/const.hh>

            template <class GF, class DT>
            std::pair<std::vector<DT>, std::vector<typename GF::RangeType>>
            sample(const GF &gf, DT &start, DT &end, int n)
            {
              Dune::Fem::LineSegmentSampler<typename GF::GridPartType> sampler(gf.gridPart(),start,end);
              std::vector<DT> coords(n);
              std::vector<typename GF::RangeType> values(n);
              sampler(gf,values);
              sampler.samplePoints(coords);
              return std::make_pair(coords,values);
            }
            #endif

            """
            self.lineSampler = algorithm.load('sample',
                                              io.StringIO(_lineSampleCode),
                                              self.gridFunction, x0, x1, N)

        p, v = self.lineSampler(self.gridFunction, x0, x1, N)
        x, y = numpy.zeros(len(p)), numpy.zeros(len(p))
        length = (x1 - x0).two_norm
        for i in range(len(x)):
            x[i] = (p[i] - x0).two_norm / length
            y[i] = v[i][0]
        return x, y
Ejemplo n.º 3
0
    if t >= saveStep:
        print(t,
              grid.size(0),
              sum(estimate.dofVector),
              hTol,
              "# timestep",
              flush=True)
        plot(solution[1], figsize=(15, 4))
        saveStep += 100

# <markdowncell>
# Postprocessing
# Show solution along a given line

# <codecell>
x0 = FieldVector([0.25, 0.65])
x1 = FieldVector([0.775, 0.39])
p, v = algorithm.run('sample', 'utility.hh', solution, x0, x1, 1000)

from matplotlib import pyplot
import numpy

x = numpy.zeros(len(p))
y = numpy.zeros(len(p))
l = (x1 - x0).two_norm
for i in range(len(x)):
    x[i] = (p[i] - x0).two_norm / l
    y[i] = v[i][1]
pyplot.plot(x, y)
pyplot.show()
Ejemplo n.º 4
0
def function(gv,callback,includeFiles=None,*args,name=None,order=None,dimRange=None):
    if name is None:
        name = "tmp"+str(gv._gfCounter)
        gv.__class__._gfCounter += 1
    if isString(callback):
        if includeFiles is None:
            raise ValueError("""if `callback` is the name of a C++ function
            then at least one include file containing that function must be
            provided""")

        # unique header guard is added further down
        source  = '#include <config.h>\n\n'
        source += '#define USING_DUNE_PYTHON 1\n\n'
        includes = []
        if isString(includeFiles):
            if not os.path.dirname(includeFiles):
                with open(includeFiles, "r") as include:
                    source += include.read()
                source += "\n"
            else:
                source += "#include <"+includeFiles+">\n"
                includes += [includeFiles]
        elif hasattr(includeFiles,"readable"): # for IOString
            with includeFiles as include:
                source += include.read()
            source += "\n"
        elif isinstance(includeFiles, list):
            for includefile in includeFiles:
                if not os.path.dirname(includefile):
                    with open(includefile, "r") as include:
                        source += include.read()
                    source += "\n"
            else:
                source += "#include <"+includefile+">\n"
                includes += [includefile]
        includes += gv.cppIncludes
        argTypes = []
        for arg in args:
            t,i = cppType(arg)
            argTypes.append(t)
            includes += i

        signature = callback + "( " + ", ".join(argTypes) + " )"
        moduleName = "gf_" + hashIt(signature) + "_" + hashIt(source)

        # add unique header guard with moduleName
        source = '#ifndef Guard_'+moduleName+'\n' + \
                 '#define Guard_'+moduleName+'\n\n' + \
                 source

        includes = sorted(set(includes))
        source += "".join(["#include <" + i + ">\n" for i in includes])
        source += "\n"
        source += '#include <dune/python/grid/function.hh>\n'
        source += '#include <dune/python/pybind11/pybind11.h>\n'
        source += '\n'

        source += "PYBIND11_MODULE( " + moduleName + ", module )\n"
        source += "{\n"
        source += "  module.def( \"gf\", [module] ( "+gv.cppTypeName + " &gv"+"".join([", "+argTypes[i] + " arg" + str(i) for i in range(len(argTypes))]) + " ) {\n"
        source += "      auto callback="+callback+"<"+gv.cppTypeName+">( "+",".join(["arg"+str(i) for i in range(len(argTypes))]) +"); \n"
        source += "      return Dune::Python::registerGridFunction<"+gv.cppTypeName+",decltype(callback)>(module,pybind11::cast(gv),\"tmp\",callback);\n"
        source += "    },"
        source += "    "+",".join(["pybind11::keep_alive<0,"+str(i+1)+">()" for i in range(len(argTypes)+1)])
        source += ");\n"
        source += "}\n"
        source += "#endif\n"
        gf = builder.load(moduleName, source, signature).gf(gv,*args)
    else:
        if len(inspect.signature(callback).parameters) == 1: # global function, turn into a local function
            callback_ = callback
            callback = lambda e,x: callback_(e.geometry.toGlobal(x))
        else:
            callback_ = None
        if dimRange is None:
            # if no `dimRange` attribute is set on the callback,
            # try to evaluate the function to determin the dimension of
            # the return value. This can fail if the function is singular in
            # the computational domain in which case an exception is raised
            e = gv.elements.__iter__().__next__()
            try:
                y = callback(e,e.referenceElement.position(0,0))
            except ArithmeticError:
                try:
                    y = callback(e,e.referenceElement.position(0,2))
                except ArithmeticError:
                    raise TypeError("can not determin dimension of range of "+
                      "given grid function due to arithmetic exceptions being "+
                      "raised. Add a `dimRange` parameter to the grid function to "+
                      "solve this issue - set `dimRange`=0 for a scalar function.")
            try:
                dimRange = len(y)
            except TypeError:
                dimRange = 0
        if dimRange > 0:
            scalar = "false"
        else:
            scalar = "true"
        FieldVector(dimRange*[0]) # register FieldVector for the return value
        if not dimRange in gv.__class__._functions.keys():
            # unique header key is added further down
            source  = '#include <config.h>\n\n'
            source += '#define USING_DUNE_PYTHON 1\n\n'
            includes = gv.cppIncludes

            signature = gv.cppTypeName+"::gf<"+str(dimRange)+">"
            moduleName = "gf_" + hashIt(signature) + "_" + hashIt(source)

            # add unique header guard with moduleName
            source = '#ifndef Guard_'+moduleName+'\n' + \
                     '#define Guard_'+moduleName+'\n\n' + \
                     source

            includes = sorted(set(includes))
            source += "".join(["#include <" + i + ">\n" for i in includes])
            source += "\n"
            source += '#include <dune/python/grid/function.hh>\n'
            source += '#include <dune/python/pybind11/pybind11.h>\n'
            source += '\n'

            source += "PYBIND11_MODULE( " + moduleName + ", module )\n"
            source += "{\n"
            source += "  typedef pybind11::function Evaluate;\n";
            source += "  Dune::Python::registerGridFunction< "+gv.cppTypeName+", Evaluate, "+str(dimRange)+" >( module, \"gf\", "+scalar+" );\n"
            source += "}\n"
            source += "#endif\n"
            gfModule = builder.load(moduleName, source, signature)
            gfFunc = getattr(gfModule,"gf"+str(dimRange))
            if callback_ is not None:
                gfFunc.localCall = gfFunc.__call__
                feval = lambda self,e,x=None: callback_(e) if x is None else self.localCall(e,x)
                subclass = type(gfFunc.__name__, (gfFunc,), {"__call__": feval})
                gv.__class__._functions[dimRange] = subclass
            else:
                gv.__class__._functions[dimRange] = gfFunc
        gf = gv.__class__._functions[dimRange](gv,callback)
    def gfPlot(gf, *args, **kwargs):
        gf.grid.plot(gf,*args,**kwargs)
    gf.plot = gfPlot.__get__(gf)
    gf.name = name
    gf.order = order
    return gf
Ejemplo n.º 5
0
#
# .. _algorithms: topics.rst

# # Dense Vectors and the Geometry Classes
# A quick survey of Dune-Common and Dune-Geometry
# The core module Dune-Common provides some classes for dense linear algebra.
# The `FieldVector` and `FieldMatrix` classes are heavily used in the grid
# geometry realizations. The conceptional basis for these geometries is
# provided by Dune-Geometry, providing, for example, reference elements and
# quadrature rules.
# <codecell>

import time, numpy, math, sys
import matplotlib.pyplot as pyplot
from dune.common import FieldVector, FieldMatrix
x = FieldVector([0.25, 0.25, 0.25])

import dune.geometry
geometryType = dune.geometry.simplex(2)
referenceElement = dune.geometry.referenceElement(geometryType)
print("\t".join(str(c) for c in referenceElement.corners))

for p in dune.geometry.quadratureRule(geometryType, 3):
    print(p.position, p.weight)

# <markdowncell>
# # Grid Construction and Basic Interface
# We now move on to the Dune-Grid module. First let us discuss different
# possibilities of constructing a grid.
# <codecell>
Ejemplo n.º 6
0
        if scvf.ipGlobal.two_norm < 0.25:
            return 1.0
        else:
            return 0.0

    def initial(self, entity):
        return 0.0


problem = Problem()

######################
# Transport equation #
######################

velocity = FieldVector([1] * dimension)
upwindWeight = 1.0


def advectiveFlux(insideConcentration, outsideConcentration, normal):
    normalVelocity = velocity * normal
    upwindConcentration = insideConcentration
    downwindConcentration = outsideConcentration
    if normalVelocity < 0.0:
        upwindConcentration, downwindConcentration = downwindConcentration, upwindConcentration
    return normalVelocity * (upwindWeight * upwindConcentration +
                             (1.0 - upwindWeight) * downwindConcentration)


##########################
# Define solution vector #
Ejemplo n.º 7
0
# <markdowncell>
# Instead of plotting this using paraview we want to only study the
# solution along a single line. This requires findings points
# $x_i = x_0+\frac{i}{N}(x1-x0)$ for $i=0,\dots,N$ within the unstructured
# grid. This would be expensive to compute on the Python so we implement
# this algorithm in C++ using the `LineSegmentSampler` class available in
# `Dune-Fem`. The resulting `algorithm` returns a pair of two lists with
# coordinates $x_i$ and the values of the grid function at these points:
#
# .. literalinclude:: utility.hh
#
# <codecell>
import dune.generator.algorithm as algorithm
from dune.common import FieldVector
x0, x1 = FieldVector([0, 0, 0]), FieldVector([0, 0, 1])
p, v = algorithm.run('sample', 'utility.hh', uh3d, x0, x1, 100)
x, y = numpy.zeros(len(p)), numpy.zeros(len(p))
length = (x1 - x0).two_norm
for i in range(len(x)):
    x[i] = (p[i] - x0).two_norm / length
    y[i] = v[i][0]
pyplot.plot(x, y)
pyplot.show()

# <markdowncell>
# **Note**: the coordinates returned are always in the interval $[0,1]$ so
# if physical coordinates are required, they need to be rescaled.
# Also, function values returned by the `sample` function
# are always of a `FieldVector` type, so that even for a scalar example
# a `v[i]` is a vector of dimension one, so that `y[i]=v[i][0]` has to be
Ejemplo n.º 8
0
op = create.operator("galerkin", inner(jump(u),jump(v))*dS, spc)
w = spc.interpolate([0],name="tmp")
op(uh, w)
dgError = [ math.sqrt( integrate(grid,(uh[0]-exact[0])**2,order=7) ),
            math.sqrt( integrate(grid,inner(grad(uh[0]-exact[0]),grad(uh[0]-exact[0])),order=7)\
            + w.scalarProductDofs(uh)) ]
l2Errors = [dgError[0]]
h1Errors = [dgError[1]]

zh = spc.interpolate([0],name="dual_h")
dualOp = create.scheme("galerkin", [adjoint(a)==0],
                 spc, solver="cg",
                 parameters={"newton." + k: v for k, v in newtonParameter.items()})
pointFunctional = spc.interpolate([0],name="pointFunctional")
point = FieldVector([0.6,0.4])
errors = [ expression2GF(grid, exact-s, reconOrder) for s in solutions ]
dualErrors = algorithm.run('pointFunctional', 'pointfunctional.hh', point, pointFunctional, *errors)
dualOp.solve(target=zh, rhs=pointFunctional)
dualWeight.project(zh-zh)

for i in range(levels):
        if error[2][useEstimate] < tolerance:
            print("COMPLETED:",error[2][useEstimate],"<",tolerance)
            break
        marked = mark(estimate, error[2][useEstimate]/grid.size(0))
        print("elements marked:", marked,"/",grid.size(0),flush=True)
        if sum(marked)==0: break
        adapt(uh)
        loadBalance(uh)
        level += 1
Ejemplo n.º 9
0
def testGF_second(gridView):
    gf1 = gridView.function(lambda e,x:\
              math.sin(math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])))

    if True:
        a = 2.
        gf1 = gridView.function(lambda e,x:\
                math.sin(a*math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])),
                name="gf1")
        lgf1 = gf1.localFunction()
        average1 = 0
        for e in gridView.elements:
            lgf1.bind(e)
            average1 += lgf1([0.5, 0.5]) * e.geometry.volume
        # print(average1)
        # gf1.plot()
        gf2 = gridView.function("myFunction",
                                StringIO(codeFunc),
                                a,
                                name="gf2")
        lgf2 = gf2.localFunction()
        average2 = 0
        for e in gridView.elements:
            lgf2.bind(e)
            average2 += lgf2([0.5, 0.5]) * e.geometry.volume
        # print(average2)
        # gf2.plot()
        # assert abs(average1-average2)<1e-12
        diff = 0
        for e in gridView.elements:
            lgf1.bind(e)
            lgf2.bind(e)
            diff += abs(lgf1([0.5, 0.5]) - lgf2([0.5, 0.5]))
        assert diff < 1e-12

    if True:
        gf1 = gridView.function(lambda e,x:\
                [math.sin(2*math.pi*(e.geometry.toGlobal(x)[0]+e.geometry.toGlobal(x)[1])),\
                 (e.geometry.toGlobal(x)[0]-0.5)*2],
                name="gf1")
        lgf1 = gf1.localFunction()
        average1 = 0
        for e in gridView.elements:
            lgf1.bind(e)
            average1 += sum(lgf1([0.5, 0.5])) * e.geometry.volume
        # print(average1)
        # gf1.plot()
        a = FieldVector([2])
        gf2 = gridView.function("myVecFunction",
                                StringIO(codeVecFunc),
                                a,
                                gf1,
                                name="gf2")
        lgf2 = gf2.localFunction()
        average2 = 0
        for e in gridView.elements:
            lgf2.bind(e)
            average2 += sum(lgf2([0.5, 0.5])) * e.geometry.volume
        # print(average2)
        # gf2.plot()
        assert abs(average1 - average2) < 1e-12
        diff = 0
        for e in gridView.elements:
            lgf1.bind(e)
            lgf2.bind(e)
            diff += abs(lgf1([0.5, 0.5]).two_norm - lgf2([0.5, 0.5]).two_norm)
        assert diff < 1e-12
        a[0] = 3
        diff = 0
        for e in gridView.elements:
            lgf1.bind(e)
            lgf2.bind(e)
            v = lgf1([0.5, 0.5])
            v[1] *= 3. / 2.
            diff += abs(v.two_norm - lgf2([0.5, 0.5]).two_norm)
        assert diff < 1e-12

        gridView.writeVTK("test_gf", pointdata=[gf1, gf2])

    if False:
        a = 2.

        @gridFunction(gridView)
        def gf1(e, x):
            return math.sin(
                a * math.pi *
                (e.geometry.toGlobal(x)[0] + e.geometry.toGlobal(x)[1]))

        lgf1 = gf1.localFunction()
        average1 = 0
        for e in gridView.elements:
            lgf1.bind(e)
            average1 += lgf1([0.5, 0.5]) * e.geometry.volume
        # print(average1)
        # gf1.plot()
        @gridFunction(gridView)
        def gf2(x):
            return math.sin(a * math.pi * (x[0] + x[1]))

        gf2 = gridView.function("myFunction",
                                StringIO(codeFunc),
                                a,
                                name="gf2")
        lgf2 = gf2.localFunction()
        average2 = 0
        for e in gridView.elements:
            lgf2.bind(e)
            average2 += lgf2([0.5, 0.5]) * e.geometry.volume
        # print(average2)
        # gf2.plot()
        assert abs(average1 - average2) < 1e-12
        diff = 0
        for e in gridView.elements:
            lgf1.bind(e)
            lgf2.bind(e)
            diff += abs(lgf1([0.5, 0.5]) - lgf2([0.5, 0.5]))
        assert diff < 1e-12