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
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)
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)
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))
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)
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)
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)
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
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
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
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)
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]()
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)
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]()
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
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
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)
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)
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
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())
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) )
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()
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)
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)
def load(includes, typeName, *args): includes = includes + ["dune/python/common/numpycommdatahandle.hh"] moduleName = "numpycommdatahandle_" + hashIt(typeName) return generator.load(includes, typeName, moduleName, *args)
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
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
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)
def load(includes, typeName, *args): includes = includes + inc moduleName = namespace + "_" + baseType + "_" + hashIt(typeName) return generator.load(includes, typeName, moduleName, *args)
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)