Beispiel #1
0
def modelSignature(form,*args):
    dirichletBCs = [str(arg.ufl_value) for arg in args if isinstance(arg, DirichletBC)]
    expr = [str(arg) for arg in args if isinstance(arg, Expr)]
    sig = form.signature()
    if len(dirichletBCs) > 0:
        dirichletBCs.append(sig)
        sig = hashIt( dirichletBCs )
    if len(expr) > 0:
        expr.append(sig)
        sig = hashIt( expr )
    return sig
Beispiel #2
0
def persistentContainer(hgrid, codim, dimension):
    includes = hgrid._includes + ["dune/python/grid/persistentcontainer.hh"]
    typeName = "Dune::PersistentContainer<" + hgrid._typeName + ", Dune::FieldVector<double," + str(
        dimension) + ">>"
    moduleName = "persistentcontainer_" + hashIt(typeName)
    module = pcGenerator.load(includes, typeName, moduleName)
    return module.PersistentContainer(hgrid, codim)
Beispiel #3
0
def PrintProblemTest(problem):
    includes = problem._includes + ["test/python/test_boundaryloop.hh"]
    typeName = "Dumux::Python::PrintProblemTest<{}>".format(problem._typeName)
    moduleName = moduleName = "printbs_" + hashIt(problem._typeName)
    generator = SimpleGenerator("PrintProblemTest", "Dumux::Python")
    module = generator.load(includes, typeName, moduleName)
    return module.PrintProblemTest(problem)
Beispiel #4
0
    def __init__(self, *, inheritsFrom, gridGeometry, scalar: str = "double"):

        inheritsFromNames = []
        for parentModel in inheritsFrom:
            if isinstance(parentModel, str):
                inheritsFromNames.append(parentModel)
            elif isinstance(parentModel, (CppTypeTag, TypeTag)):
                inheritsFromNames.append(parentModel.name)
            else:
                raise ValueError(
                    "Arguments passed to inheritsFrom must be either names (strings) of "
                    "known TypeTags, TypeTag objects or CppTypeTag objects.")

        # generate a generic name
        genericName = "TypeTag" + hashIt("".join(inheritsFromNames) +
                                         gridGeometry._typeName + scalar)

        # deduce the discretization tag from the grid geometry
        discretizationMethod = gridGeometry.discMethod
        discretizationMap = {
            "box": "BoxModel",
            "cctpfa": "CCTpfaModel",
        }
        if discretizationMethod in discretizationMap:
            inheritsFrom += [discretizationMap[discretizationMethod]]

        # call parent constructor
        super().__init__(name=genericName,
                         inheritsFrom=inheritsFrom,
                         gridGeometry=gridGeometry)

        # set the scalar type
        self.__setitem__("Scalar", Property.fromCppType(scalar))
Beispiel #5
0
def levelView(hgrid, level):
    includes = hgrid._includes + ["dune/python/grid/gridview.hh"]
    typeName = "typename " + hgrid._typeName + "::LevelGridView"
    moduleName = "view_" + hashIt(typeName)
    module = gvGenerator.load(includes, typeName, moduleName)
    addAttr(module, module.GridView)
    return hgrid._levelView(level)
Beispiel #6
0
def _createPorousMediumFlowVelocityOutput(*, gridVariables):
    """Create a PorousMediumFlowVelocityOutput"""

    includes = gridVariables._includes
    includes += [
        "dumux/python/porousmediumflow/velocityoutput.hh",
        "dumux/io/velocityoutput.hh"
    ]
    fluxVarsType = (
        f"Dumux::GetPropType<{gridVariables.model.cppType}, Dumux::Properties::FluxVariables>"
    )
    typeName = f"Dumux::PorousMediumFlowVelocityOutput<{gridVariables._typeName}, {fluxVarsType}>"
    moduleName = "porousmediumflowvelocityoutput_" + hashIt(typeName)
    baseClass = [f"Dumux::VelocityOutput<{gridVariables._typeName}>"]
    generator = SimpleGenerator("PorousMediumFlowVelocityOutput",
                                "Dumux::Python")
    module = generator.load(
        includes,
        typeName,
        moduleName,
        holder="std::shared_ptr",
        preamble=gridVariables.model.cppHeader,
        baseClasses=baseClass,
    )
    return module.PorousMediumFlowVelocityOutput(gridVariables)
Beispiel #7
0
def loadvec(includes, typeName, constructors=None, methods=None):
    includes = includes + [
        "dune/python/common/fvector.hh", "dune/python/istl/bvector.hh"
    ]
    typeHash = "istlbvector_" + hashIt(typeName)
    return generatorvec.load(includes, typeName, typeHash, constructors,
                             methods)
Beispiel #8
0
def module(dim):
    typeName = "Dune::Geo::ReferenceElement<Dune::Geo::ReferenceElementImplementation<double," + str(dim) + "> >"
    includes = ["dune/python/geometry/referenceelements.hh"]
    typeHash = "referenceelements_" + hashIt(typeName)
    generator = SimpleGenerator("ReferenceElements", "Dune::Python")
    m = generator.load(includes, typeName, typeHash)
    return m
Beispiel #9
0
def indexSet(gv):
    try:
        return gv._indexSet
    except TypeError:
        includes = gv.cppIncludes + ["dune/python/grid/indexset.hh"]
        typeName = gv.cppTypeName+"::IndexSet"
        moduleName = "indexset_" + hashIt(typeName)
        module = isGenerator.load(includes, typeName, moduleName)
        return gv._indexSet
Beispiel #10
0
def module(includes, typeName, *args, **kwargs):
    try:
        generator = kwargs.pop("generator")
    except KeyError:
        generator = SimpleGenerator("HierarchicalGrid", "Dune::Python")
    includes = includes + ["dune/python/grid/hierarchical.hh"]
    typeHash = "hierarchicalgrid_" + hashIt(typeName)
    kwargs["dynamicAttr"] = True
    module = generator.load(includes, typeName, typeHash, *args, **kwargs)
    return module
Beispiel #11
0
def _loadVec(includes, typeName, constructors=None, methods=None):
    from dune.generator.generator import SimpleGenerator
    from dune.common.hashit import hashIt
    generator = SimpleGenerator("FieldVector", "Dune::Python")
    includes = includes + ["dune/python/common/fvector.hh"]
    typeHash = "fieldvector_" + hashIt(typeName)
    return generator.load(includes,
                          typeName,
                          typeHash,
                          constructors,
                          methods,
                          bufferProtocol=True)
Beispiel #12
0
def BoundaryTypes(numEq=1):
    # only copmile this once per numEq
    cacheKey = "BoundaryTypes_{}".format(numEq)
    try:
        return globals()[cacheKey]()
    except KeyError:
        includes = ["dumux/python/common/boundarytypes.hh"]
        typeName = "Dumux::BoundaryTypes<{}>".format(numEq)
        moduleName = "boundarytypes_" + hashIt(typeName)
        generator = SimpleGenerator("BoundaryTypes", "Dumux::Python")
        module = generator.load(includes, typeName, moduleName)
        globals().update({cacheKey: module.BoundaryTypes})
    return globals()[cacheKey]()
Beispiel #13
0
def _createVtkOutputModule(*, gridVariables, solutionVector, name):
    """Construct a VtkOutputModule"""

    includes = gridVariables._includes + solutionVector._includes
    includes += [
        "dumux/python/io/vtkoutputmodule.hh", "dumux/io/vtkoutputmodule.hh"
    ]
    typeName = f"Dumux::VtkOutputModule<{gridVariables._typeName}, {solutionVector._typeName}>"
    moduleName = "vtkoutputmodule_" + hashIt(typeName)
    generator = SimpleGenerator("VtkOutputModule", "Dumux::Python")
    module = generator.load(includes,
                            typeName,
                            moduleName,
                            preamble=gridVariables.model.cppHeader)
    return module.VtkOutputModule(gridVariables, solutionVector, name)
Beispiel #14
0
def _createBoundaryTypes(numEq=1):
    """Create BoundaryTypes instances"""

    # only compile this once per numEq
    cacheKey = f"BoundaryTypes_{numEq}"
    try:
        return globals()[cacheKey]()
    except KeyError:
        includes = ["dumux/python/common/boundarytypes.hh"]
        typeName = f"Dumux::BoundaryTypes<{numEq}>"
        moduleName = "boundarytypes_" + hashIt(typeName)
        generator = SimpleGenerator("BoundaryTypes", "Dumux::Python")
        module = generator.load(includes, typeName, moduleName)
        globals().update({cacheKey: module.BoundaryTypes})
    return globals()[cacheKey]()
Beispiel #15
0
 def createModule(numEq):
     priVarType = "Dune::FieldVector<double, {}>".format(numEq)
     ggType = gridGeometry._typeName
     problemType = "Dumux::Python::FVProblem<{}, {}>".format(
         ggType, priVarType)
     includes = gridGeometry._includes + [
         "dumux/python/common/fvproblem.hh"
     ]
     moduleName = "fvproblem_" + hashIt(problemType)
     holderType = "std::shared_ptr<{}>".format(problemType)
     generator = SimpleGenerator("FVProblem", "Dumux::Python")
     module = generator.load(includes,
                             problemType,
                             moduleName,
                             options=[holderType])
     return module
Beispiel #16
0
 def createModule(numEq):
     priVarType = f"Dune::FieldVector<double, {numEq}>"
     ggType = gridGeometry._typeName
     enableIntDirConstraint = "true" if enableInternalDirichletConstraints else "false"
     problemType = f"Dumux::Python::FVProblem<{ggType}, {priVarType}, {enableIntDirConstraint}>"
     includes = gridGeometry._includes + [
         "dumux/python/common/fvproblem.hh"
     ]
     moduleName = "fvproblem_" + hashIt(problemType)
     holderType = f"std::shared_ptr<{problemType}>"
     generator = SimpleGenerator("FVProblem", "Dumux::Python")
     module = generator.load(includes,
                             problemType,
                             moduleName,
                             options=[holderType])
     return module
Beispiel #17
0
def _createFVAssembler(*,
                       problem,
                       gridVariables,
                       model,
                       diffMethod="numeric",
                       isImplicit=True):
    """
    Create an FVAssembler object

    Args:
        problem: A problem instance (boundary & initial conditions)
        gridVariables: A grid variable instance (primary & secondary variables defined on a grid)
        model: A DuMux model configuration instance
        diffMethod (str): The method to compute derivatives of the residual (numeric or analytic)
        isImplicit (bool): If the time discretization method is implicit or explicit

    Returns:
        An assembler object (Python-bindings of the corresponding C++ type)

    Usage:
        assembler = FVAssembler(
            problem=problem, gridVariables=gridVars, model=model, diffMethod=diffMethod
        )
    """

    if diffMethod == "numeric":
        cppDiffMethod = "Dumux::DiffMethod::numeric"
    elif diffMethod == "analytic":
        cppDiffMethod = "Dumux::DiffMethod::analytic"
    else:
        raise ValueError(f"Unknown diffMethod {diffMethod}")

    assemblerType = f"Dumux::FVAssembler<{model.cppType}, {cppDiffMethod}, {int(isImplicit)}>"
    includes = (problem._includes + problem.gridGeometry()._includes +
                ["dumux/assembly/fvassembler.hh"])
    includes += ["dumux/python/assembly/fvassembler.hh"]

    moduleName = "fvassembler_" + hashIt(assemblerType)
    generator = SimpleGenerator("FVAssembler", "Dumux::Python")
    module = generator.load(
        includes,
        assemblerType,
        moduleName,
        holder="std::shared_ptr",
        preamble=model.cppHeader,
    )
    return module.FVAssembler(problem, problem.gridGeometry(), gridVariables)
Beispiel #18
0
def _createGridGeometry(gridView, discMethod="cctpfa"):
    """Construct a GridGeometry from a gridView"""

    includes = gridView._includes + ["dumux/python/discretization/gridgeometry.hh"]

    if discMethod == "cctpfa":
        includes += ["dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh"]
        typeName = "Dumux::CCTpfaFVGridGeometry<" + gridView._typeName + ">"
    elif discMethod == "box":
        includes += ["dumux/discretization/box/fvgridgeometry.hh"]
        typeName = "Dumux::BoxFVGridGeometry<double, " + gridView._typeName + ">"
    else:
        raise ValueError(f"Unknown discMethod {discMethod}")

    moduleName = "gridgeometry_" + hashIt(typeName)
    holderType = f"std::shared_ptr<{typeName}>"
    generator = SimpleGenerator("GridGeometry", "Dumux::Python")
    module = generator.load(includes, typeName, moduleName, options=[holderType])
    return module.GridGeometry(gridView)
Beispiel #19
0
 def createModule(numEq):
     priVars = f"Dune::FieldVector<double, {numEq}>"
     ggType = gridGeometry._typeName
     spType = spatialParams._typeName
     enableIDC = "true" if enableInternalDirichletConstraints else "false"
     problemType = ("Dumux::Python::PorousMediumFlowProblem"
                    f"<{ggType}, {priVars}, {spType}, {enableIDC}>")
     includes = [
         *(gridGeometry._includes),
         *(spatialParams._includes),
         *["dumux/python/porousmediumflow/problem.hh"],
     ]
     moduleName = "fvproblem_" + hashIt(problemType)
     generator = SimpleGenerator("PorousMediumFlowProblem", "Dumux::Python")
     module = generator.load(includes,
                             problemType,
                             moduleName,
                             holder="std::shared_ptr")
     return module
Beispiel #20
0
def _createGridVariables(*, problem, model):
    """Construct a GridGeometry from problem and the model"""

    includes = [
        "dumux/discretization/fvgridvariables.hh",
        "dumux/python/discretization/gridvariables.hh",
    ]
    ggeo = f"Dumux::GetPropType<{model.cppType}, Dumux::Properties::GridGeometry>"
    gvv = f"Dumux::GetPropType<{model.cppType}, Dumux::Properties::GridVolumeVariables>"
    gfc = f"Dumux::GetPropType<{model.cppType}, Dumux::Properties::GridFluxVariablesCache>"
    typeName = f"Dumux::FVGridVariables<{ggeo}, {gvv}, {gfc}>"

    moduleName = "gridvariables_" + hashIt(typeName)
    holderType = f"std::shared_ptr<{typeName}>"
    generator = SimpleGenerator("GridVariables", "Dumux::Python")
    module = generator.load(
        includes, typeName, moduleName, options=[holderType], preamble=model.cppHeader
    )
    module.GridVariables.model = property(lambda self: model)
    return module.GridVariables(problem, problem.gridGeometry())
Beispiel #21
0
def uflSignature(form,*args):
    import ufl
    from ufl.algorithms.renumbering import renumber_indices
    sig = ''
    hashList  = [str(arg) for arg in args if not isinstance(arg,ufl.core.expr.Expr)]
    #   the following fails in the ufl algorithm in the rentrant corner problem:
    #   phi = atan_2(x[1], x[0]) + conditional(x[1] < 0, 2*math.pi, 0)
    #   create.function("ufl",gridview=grid,name="tmp",order=1,ufl=phi)
    # hashList += [str(renumber_indices(arg)) for arg in args if isinstance(arg,ufl.core.expr.Expr)]
    for arg in args:
        if isinstance(arg,ufl.core.expr.Expr):
            try:
                hashList += [str(renumber_indices(arg))]
            except ValueError:  # I don't think this should happen but it does :-<
                hashList += [str(arg)]

    if form is not None:
        hashList.append(form.signature())
    hashList = [h.split(" at ")[0] for h in hashList]
    return hashIt( sorted(hashList) )
Beispiel #22
0
def _createFluidSystem(name, *, component, scalar: Property = None):
    """Construct a FluidSystem"""

    includes = component._includes + [
        "dumux/python/material/fluidsystems/fluidsystem.hh"
    ]

    if scalar is None:
        scalar = Property.fromCppType("double")
    scalarType = scalar.cppType

    availableFluidSystems = {
        "OnePLiquid": {
            "includes": ["dumux/material/fluidsystems/1pliquid.hh"],
            "type":
            f"Dumux::FluidSystems::OnePLiquid<{scalarType}, {component._typeName}>",
        },
        "OnePGas": {
            "includes": ["dumux/material/fluidsystems/1pgas.hh"],
            "type":
            f"Dumux::FluidSystems::OnePGas<{scalarType}, {component._typeName}>",
        },
    }
    if name not in availableFluidSystems:
        raise NotImplementedError("FluidSystem of type " + name +
                                  " not implemented.\n"
                                  "Available types are " +
                                  ", ".join(availableFluidSystems.keys()))

    includes += availableFluidSystems[name]["includes"]
    typeName = availableFluidSystems[name]["type"]

    moduleName = "fluidsystem_" + hashIt(typeName)
    generator = SimpleGenerator("FluidSystem", "Dumux::Python")
    module = generator.load(includes, typeName, moduleName)
    return module.FluidSystem()
Beispiel #23
0
def loadmatrixindexset(includes, typeName, constructors=None, methods=None):
    includes = includes + ["dune/python/istl/matrixindexset.hh"]
    typeHash = "matrixindexset_" + hashIt(typeName)
    return generatormatrixindexset.load(includes, typeName, typeHash,
                                        constructors, methods)
Beispiel #24
0
def load(includes, typeName, constructors=None, methods=None):
    includes = includes + ["dune/python/istl/bcrsmatrix.hh"]
    typeHash = "istlbcrsmatrix_" + hashIt(typeName)
    return generator.load(includes, typeName, typeHash, constructors, methods)
Beispiel #25
0
def load(includes, typeName, *args):
    includes = includes + ["dune/python/common/numpycommdatahandle.hh"]
    moduleName = "numpycommdatahandle_" + hashIt(typeName)
    return generator.load(includes, typeName, moduleName, *args)
Beispiel #26
0
def viewModule(includes, typeName, *args, **kwargs):
    includes = includes + ["dune/python/grid/gridview.hh"]
    moduleName = "view_" + hashIt(typeName)
    module = gvGenerator.load(includes, typeName, moduleName, *args, **kwargs)
    addAttr(module, module.GridView)
    return module
Beispiel #27
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
Beispiel #28
0
def mapper(gv,layout):
    includes = gv.cppIncludes + ["dune/python/grid/mapper.hh"]
    typeName = "Dune::MultipleCodimMultipleGeomTypeMapper< "+gv.cppTypeName+" >"
    moduleName = "mcmgmapper_" + hashIt(typeName)
    module = mcmgGenerator.load(includes, typeName, moduleName)
    return gv._mapper(layout)
Beispiel #29
0
 def load(includes, typeName, *args):
     includes = includes + inc
     moduleName = namespace + "_" + baseType + "_" + hashIt(typeName)
     return generator.load(includes, typeName, moduleName, *args)
Beispiel #30
0
 def name(self):
     from dune.common.hashit import hashIt
     if self.virtualize:
         return self.integrands.baseName + '_' + self.signature() + '_' + hashIt(self.gridType)
     else:
         return self.integrands.baseName + '_nv_' + self.signature() + '_' + hashIt(self.gridType)