diff --git a/dumux/python/common/fvproblem.hh b/dumux/python/common/fvproblem.hh index 86eb699bc1375c887dc0975f9e23e8bcb2100c70..5da2a9f348ab750cba1d01c75827f90ba0f35802 100644 --- a/dumux/python/common/fvproblem.hh +++ b/dumux/python/common/fvproblem.hh @@ -35,6 +35,7 @@ #include #include #include +#include namespace Dumux::Python { @@ -42,12 +43,13 @@ namespace Dumux::Python { * \ingroup Common * \brief A C++ wrapper for a Python problem */ -template +template class FVProblem { public: using GridGeometry = GridGeometry_; - using Scalar = typename PrimaryVariables::value_type; + using SpatialParams = SpatialParams_; + using Scalar = typename GridGeometry::GridView::ctype; using NumEqVector = Dune::FieldVector; using Element = typename GridGeometry::GridView::template Codim<0>::Entity; using FVElementGeometry = typename GridGeometry::LocalView; @@ -60,11 +62,13 @@ public: using BoundaryTypes = Dumux::BoundaryTypes; FVProblem(std::shared_ptr gridGeometry, + std::shared_ptr spatialParams, pybind11::object pyProblem) : gridGeometry_(gridGeometry) , pyProblem_(pyProblem) , name_("python_problem") , paramGroup_("") + , spatialParams_(spatialParams) { if (pybind11::hasattr(pyProblem_, "name")) name_ = pyProblem.attr("name")().template cast(); @@ -73,6 +77,11 @@ public: paramGroup_ = pyProblem.attr("paramGroup")().template cast(); } + FVProblem(std::shared_ptr gridGeometry, + pybind11::object pyProblem) + : FVProblem(gridGeometry, std::make_shared(gridGeometry), pyProblem) + {} + const std::string& name() const { return name_; } @@ -183,19 +192,6 @@ public: return pyProblem_.attr("initial")(entity).template cast(); } - template - Scalar extrusionFactor(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const - { - return pyProblem_.attr("extrusionFactor")(element, scv).template cast(); - } - - Scalar temperatureAtPos(const GlobalPosition& globalPos) const - { - return pyProblem_.attr("temperatureAtPos")(globalPos).template cast(); - } - static constexpr bool enableInternalDirichletConstraints() { return enableInternalDirichletConstraints_; } @@ -214,14 +210,39 @@ public: pyProblem_.attr("addSourceDerivatives")(block, element, fvGeometry, scv); } + [[deprecated("extrusionFactorAtPos() should now be defined in the spatial params. This interface will be removed after 3.5.")]] + Scalar extrusionFactorAtPos(const GlobalPosition &globalPos, double defaultValue = 1.0) const + { return 1.0; } + + template + [[deprecated("extrusionFactor() should now be defined in the spatial params. This interface will be removed after 3.5.")]] + Scalar extrusionFactor(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol, + double defaultValue = 1.0) const + { return this->extrusionFactorAtPos(scv.center()); } + + [[deprecated("temperatureAtPos() should now be defined in the spatial params. This interface will be removed after 3.5.")]] + Scalar temperatureAtPos(const GlobalPosition &globalPos, int defaultValue = 1) const + { return 293.0; } + + [[deprecated("temperature() should now be defined in the spatial params. This interface will be removed after 3.5.")]] + Scalar temperature(int defaultValue = 1) const + { return this->temperature(GlobalPosition(0.0)); } + const GridGeometry& gridGeometry() const { return *gridGeometry_; } + //! Return a reference to the underlying spatial parameters + const SpatialParams& spatialParams() const + { return *spatialParams_; } + private: std::shared_ptr gridGeometry_; pybind11::object pyProblem_; std::string name_; std::string paramGroup_; + std::shared_ptr spatialParams_; }; // Python wrapper for the above FVProblem C++ class @@ -232,6 +253,12 @@ void registerFVProblem(pybind11::handle scope, pybind11::class_ gridGeometry, + std::shared_ptr spatialParams, + pybind11::object p){ + return std::make_shared(gridGeometry, spatialParams, p); + })); cls.def(pybind11::init([](std::shared_ptr gridGeometry, pybind11::object p){ return std::make_shared(gridGeometry, p); @@ -263,7 +290,6 @@ void registerFVProblem(pybind11::handle scope, pybind11::class_); cls.def("initial", &Problem::template initial); - cls.def("extrusionFactor", &Problem::template extrusionFactor); } } // end namespace Dumux::Python diff --git a/dumux/python/common/fvspatialparams.hh b/dumux/python/common/fvspatialparams.hh new file mode 100644 index 0000000000000000000000000000000000000000..9b69fe339b44d9597438fc4aafb717627212a2dd --- /dev/null +++ b/dumux/python/common/fvspatialparams.hh @@ -0,0 +1,166 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup Common + * \ingroup SpatialParameters + * \brief Basic spatial parameters to be used with finite-volume schemes. + */ +#ifndef DUMUX_PYTHON_COMMON_FVSPATIALPARAMS_HH +#define DUMUX_PYTHON_COMMON_FVSPATIALPARAMS_HH + +#include + +#include +#include +#include +#include + +namespace Dumux::Python { + +/*! + * \ingroup Common + * \ingroup SpatialParameters + * \brief The base class for spatial parameters used with finite-volume schemes. + */ +template +class FVSpatialParams +{ +public: + using GridGeometry = GridGeometry_; + using GridView = typename GridGeometry::GridView; + using Scalar = typename GridView::ctype; + using Element = typename GridView::template Codim<0>::Entity; + using SubControlVolume = typename GridGeometry::SubControlVolume; + + static constexpr bool isBox = GridGeometry::discMethod == DiscretizationMethods::box; + static constexpr int dimWorld = GridView::dimensionworld; + + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using GravityVector = Dune::FieldVector; + + FVSpatialParams(std::shared_ptr gridGeometry, + pybind11::object pySpatialParameters) + : gridGeometry_(gridGeometry) + , pySpatialParameters_(pySpatialParameters) + , gravity_(0.0) + { + if (getParam("Problem.EnableGravity")) + gravity_[dimWorld-1] = -9.81; + } + + FVSpatialParams(std::shared_ptr gridGeometry) + : gridGeometry_(gridGeometry) + , pySpatialParameters_{} + , gravity_(0.0) + { + if (getParam("Problem.EnableGravity")) + gravity_[dimWorld-1] = -9.81; + } + + /*! + * \brief Return how much the domain is extruded at a given sub-control volume. + * + * This means the factor by which a lower-dimensional (1D or 2D) + * entity needs to be expanded to get a full dimensional cell. The + * default is 1.0 which means that 1D problems are actually + * thought as pipes with a cross section of 1 m^2 and 2D problems + * are assumed to extend 1 m to the back. + */ + template + Scalar extrusionFactor(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + if (pySpatialParameters_) + { + if (pybind11::hasattr(pySpatialParameters_, "extrusionFactor")) + return pySpatialParameters_.attr("extrusionFactor")(element, scv, elemSol).template cast(); + else if (pybind11::hasattr(pySpatialParameters_, "extrusionFactorAtPos")) + return pySpatialParameters_.attr("extrusionFactorAtPos")(scv.dofPosition()).template cast(); + } + + // default + return 1.0; + } + + /*! + * \brief Return the temperature in the given sub-control volume. + */ + template + Scalar temperature(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + if (pySpatialParameters_) + { + if (pybind11::hasattr(pySpatialParameters_, "temperature")) + return pySpatialParameters_.attr("temperature")(element, scv, elemSol).template cast(); + else if (pybind11::hasattr(pySpatialParameters_, "temperatureAtPos")) + return pySpatialParameters_.attr("temperatureAtPos")(scv.dofPosition()).template cast(); + } + + // default + return 283.15; + } + + /*! + * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$. + * + * The default behaviour is a constant gravity vector; + * if the Problem.EnableGravity parameter is true, + * \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$, + * else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$. + * + * \param pos the spatial position at which to evaulate the gravity vector + */ + const GravityVector& gravity(const GlobalPosition& pos) const + { return gravity_; } + + //! The finite volume grid geometry + const GridGeometry& gridGeometry() const + { return *gridGeometry_; } + +private: + std::shared_ptr gridGeometry_; + pybind11::object pySpatialParameters_; + GravityVector gravity_; +}; + +// Python wrapper for the above FVProblem C++ class +template +void registerFVSpatialParams(pybind11::handle scope, pybind11::class_ cls) +{ + using pybind11::operator""_a; + + using GridGeometry = typename SpatialParams::GridGeometry; + + cls.def(pybind11::init([](std::shared_ptr gridGeometry, pybind11::object p){ + return std::make_shared(gridGeometry, p); + })); + + cls.def("extrusionFactor", &SpatialParams::template extrusionFactor); + cls.def("temperature", &SpatialParams::template temperature); + cls.def("gravity", &SpatialParams::gravity); + cls.def_property_readonly("gridGeometry", &SpatialParams::gridGeometry); +} + +} // namespace Dumux::Python + +#endif diff --git a/dumux/python/material/CMakeLists.txt b/dumux/python/material/CMakeLists.txt index f1c168afc35b03db804df7829820e885bd607308..8400d5f3eb5c466207b0191dc02dc25361439bef 100644 --- a/dumux/python/material/CMakeLists.txt +++ b/dumux/python/material/CMakeLists.txt @@ -1,3 +1,2 @@ add_subdirectory(components) add_subdirectory(fluidsystems) -add_subdirectory(spatialparams) diff --git a/dumux/python/material/spatialparams/CMakeLists.txt b/dumux/python/material/spatialparams/CMakeLists.txt deleted file mode 100644 index 08816c5b1a287597d371c037e0e4703c0496b7cf..0000000000000000000000000000000000000000 --- a/dumux/python/material/spatialparams/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB DUMUX_PYTHON_MATERIAL_SPATIALPARAMS_HEADERS *.hh *.inc) -install(FILES ${DUMUX_PYTHON_MATERIAL_SPATIALPARAMS_HEADERS} - DESTINATION${CMAKE_INSTALL_INCLUDEDIR}/dumux/python/material/spatialparams) diff --git a/dumux/python/porousmediumflow/problem.hh b/dumux/python/porousmediumflow/problem.hh index 7b369fade43d305c692ea3fa991475f4daa57a17..d97b8a28eb7e2fa9b041438456c0ea32fd6227f1 100644 --- a/dumux/python/porousmediumflow/problem.hh +++ b/dumux/python/porousmediumflow/problem.hh @@ -35,11 +35,11 @@ namespace Dumux::Python { * \ingroup PorousmediumflowModels * \brief A C++ wrapper for a Python PorousMediumFlow problem */ -template -class PorousMediumFlowProblem : public FVProblem +template +class PorousMediumFlowProblem +: public Dumux::Python::FVProblem { - using ParentType = FVProblem; + using ParentType = Dumux::Python::FVProblem; public: using GridGeometry = GridGeometry_; using SpatialParams = SpatialParams_; @@ -58,7 +58,7 @@ public: PorousMediumFlowProblem(std::shared_ptr gridGeometry, std::shared_ptr spatialParams, pybind11::object pyProblem) - : ParentType(gridGeometry, pyProblem) + : ParentType(gridGeometry, spatialParams, pyProblem) , spatialParams_(spatialParams) {} @@ -79,7 +79,7 @@ void registerPorousMediumFlowProblem(pybind11::handle scope, pybind11::class_ gridGeometry, - std::shared_ptr spatialParams, + std::shared_ptr spatialParams, pybind11::object p){ return std::make_shared(gridGeometry, spatialParams, p); })); @@ -109,7 +109,6 @@ void registerPorousMediumFlowProblem(pybind11::handle scope, pybind11::class_); cls.def("initial", &Problem::template initial); - cls.def("extrusionFactor", &Problem::template extrusionFactor); cls.def("gridGeometry", &Problem::gridGeometry); cls.def("spatialParams", &Problem::spatialParams); } diff --git a/dumux/python/material/spatialparams/spatialparams.hh b/dumux/python/porousmediumflow/spatialparams.hh similarity index 57% rename from dumux/python/material/spatialparams/spatialparams.hh rename to dumux/python/porousmediumflow/spatialparams.hh index 448a981491bcfca1747799614d79ee7be53d6b3b..219930927932058526e30bdc84204f3b111a2bcd 100644 --- a/dumux/python/material/spatialparams/spatialparams.hh +++ b/dumux/python/porousmediumflow/spatialparams.hh @@ -21,33 +21,32 @@ * \brief TODO: docme! */ -#ifndef DUMUX_PYTHON_MATERIAL_SPATIAL_PARAMS_HH -#define DUMUX_PYTHON_MATERIAL_SPATIAL_PARAMS_HH +#ifndef DUMUX_PYTHON_POROUSMEDIUMFLOW_FVSPATIALPARAMS_1P_HH +#define DUMUX_PYTHON_POROUSMEDIUMFLOW_FVSPATIALPARAMS_1P_HH #include #include -#include +#include namespace Dumux::Python { -template +template class FVSpatialParamsOneP -: public Dumux::FVSpatialParamsOneP> +: public Dumux::Python::FVSpatialParams { - using ThisType = FVSpatialParamsOneP; - using ParentType = Dumux::FVSpatialParamsOneP; + using ThisType = Dumux::Python::FVSpatialParamsOneP; + using ParentType = Dumux::Python::FVSpatialParams; +public: + using GridGeometry = GridGeometry_; + using Scalar = typename GridGeometry::GridView::ctype; using Element = typename GridGeometry::GridView::template Codim<0>::Entity; using SubControlVolume = typename GridGeometry::SubControlVolume; - using GlobalPosition = typename GridGeometry::GridView::template Codim<0>::Geometry::GlobalCoordinate; - -public: - using PermeabilityType = PT; FVSpatialParamsOneP(std::shared_ptr gridGeometry, pybind11::object pySpatialParams) - : ParentType(gridGeometry) + : ParentType(gridGeometry, pySpatialParams) , pySpatialParams_(pySpatialParams) {} @@ -64,8 +63,8 @@ public: template Scalar porosity(const Element& element, - const SubControlVolume& scv, - const ElementSolution& elemSol) const + const SubControlVolume& scv, + const ElementSolution& elemSol) const { if (pybind11::hasattr(pySpatialParams_, "porosity")) return pySpatialParams_.attr("porosity")(element, scv, elemSol).template cast(); @@ -73,24 +72,41 @@ public: return pySpatialParams_.attr("porosityAtPos")(scv.center()).template cast(); } + template + Scalar inertVolumeFraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol, + int compIdx) const + + { + if (pybind11::hasattr(pySpatialParams_, "inertVolumeFraction")) + return pySpatialParams_.attr("inertVolumeFraction")(element, scv, elemSol, compIdx).template cast(); + else if (pybind11::hasattr(pySpatialParams_, "inertVolumeFractionAtPos")) + return pySpatialParams_.attr("inertVolumeFractionAtPos")(scv.center(), compIdx).template cast(); + else + return 1.0 - this->porosity(element, scv, elemSol); + } + + static constexpr bool evaluatePermeabilityAtScvfIP() + { return false; } + private: pybind11::object pySpatialParams_; }; - - -template -void registerOnePSpatialParams(pybind11::handle scope, - pybind11::class_ cls) +template +void registerFVSpatialParamsOneP(pybind11::handle scope, pybind11::class_ cls) { using pybind11::operator""_a; - using GridGeometry = std::decay_t().gridGeometry())>; + using GridGeometry = typename SpatialParams::GridGeometry; - cls.def(pybind11::init([](std::shared_ptr gridGeometry, pybind11::object sp){ - return std::make_shared(gridGeometry, sp); + cls.def(pybind11::init([](std::shared_ptr gridGeometry, pybind11::object p){ + return std::make_shared(gridGeometry, p); })); - cls.def("gravity", &SP::gravity); + cls.def("permeability", &SpatialParams::template permeability); + cls.def("porosity", &SpatialParams::template porosity); + cls.def("inertVolumeFraction", &SpatialParams::template inertVolumeFraction); } } // namespace Dumux::Python diff --git a/python/dumux/common/CMakeLists.txt b/python/dumux/common/CMakeLists.txt index 21bad44ccf825f9063e6fdfac6fc8c2d58acfe09..31a5167f3d6615696e7439654851e9bb6f441092 100644 --- a/python/dumux/common/CMakeLists.txt +++ b/python/dumux/common/CMakeLists.txt @@ -1,5 +1,8 @@ add_python_targets(common __init__ + boundarytypes + fvproblem + fvspatialparams properties ) diff --git a/python/dumux/common/__init__.py b/python/dumux/common/__init__.py index 879a0f7a8f00325af079aef0defa9e41a0b4989d..f2fa10c16174a44718e47fb2f25c4a4dac6faab9 100644 --- a/python/dumux/common/__init__.py +++ b/python/dumux/common/__init__.py @@ -7,67 +7,9 @@ from dune.generator.generator import SimpleGenerator from dune.common.hashit import hashIt from dumux.common.properties import Model, Property +from dumux.common.boundarytypes import BoundaryTypes +from dumux.common.fvproblem import FVProblem +from dumux.common.fvspatialparams import FVSpatialParams from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias from ._common import * - - -@cppWrapperCreator -def _createFVProblemDecorator(gridGeometry, enableInternalDirichletConstraints=False): - """A problem decorator generator for Python problems - - from dumux.common import FVProblem - @FVProblem(gridGeometry) - class MyProblem: - ... - """ - - def createModule(numEq): - priVarType = f"Dune::FieldVector" - 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 decorateFVProblem(cls): - module = createModule(cls.numEq) - - def createFVProblem(): - return module.FVProblem(gridGeometry, cls()) - - return createFVProblem - - return decorateFVProblem - - -@cppWrapperClassAlias(creator=_createFVProblemDecorator) -class FVProblem: - """Class alias used to decorate a Python finite volume problem""" - - -@cppWrapperCreator -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]() - - -@cppWrapperClassAlias(creator=_createBoundaryTypes) -class BoundaryTypes: - """Class alias used to create a BoundaryTypes instance""" diff --git a/python/dumux/common/boundarytypes.py b/python/dumux/common/boundarytypes.py new file mode 100644 index 0000000000000000000000000000000000000000..7029b5ca2cf139fe383db9eca26b885a809fddcb --- /dev/null +++ b/python/dumux/common/boundarytypes.py @@ -0,0 +1,31 @@ +""" +Boundary types generator +""" + +from dune.generator.generator import SimpleGenerator +from dune.common.hashit import hashIt + +from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias + + +@cppWrapperCreator +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]() + + +@cppWrapperClassAlias(creator=_createBoundaryTypes) +class BoundaryTypes: + """Class alias used to create a BoundaryTypes instance""" diff --git a/python/dumux/common/fvproblem.py b/python/dumux/common/fvproblem.py new file mode 100644 index 0000000000000000000000000000000000000000..416500c3164bfb75b7f6db8348c976e4599bccb2 --- /dev/null +++ b/python/dumux/common/fvproblem.py @@ -0,0 +1,58 @@ +""" +Finite volume problem generator +""" + +from dune.generator.generator import SimpleGenerator +from dune.common.hashit import hashIt + +from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias + + +@cppWrapperCreator +def _createFVProblemDecorator( + gridGeometry, spatialParams=None, enableInternalDirichletConstraints=False +): + """A problem decorator generator for Python problems + + from dumux.common import FVProblem + @FVProblem(gridGeometry) + class MyProblem: + ... + """ + + def createModule(numEq): + ggType = gridGeometry._typeName + if spatialParams is not None: + spType = spatialParams._typeName + else: + spType = f"Dumux::Python::FVSpatialParams<{ggType}>" + + priVarType = f"Dune::FieldVector" + enableIntDirConstraint = "true" if enableInternalDirichletConstraints else "false" + problemType = ( + f"Dumux::Python::FVProblem<{ggType}, {spType}, {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 decorateFVProblem(cls): + module = createModule(cls.numEq) + + def createFVProblem(): + if spatialParams is not None: + return module.FVProblem(gridGeometry, spatialParams, cls()) + + return module.FVProblem(gridGeometry, cls()) + + return createFVProblem + + return decorateFVProblem + + +@cppWrapperClassAlias(creator=_createFVProblemDecorator) +class FVProblem: + """Class alias used to decorate a Python finite volume problem""" diff --git a/python/dumux/common/fvspatialparams.py b/python/dumux/common/fvspatialparams.py new file mode 100644 index 0000000000000000000000000000000000000000..812df3f3b6bd855180e0b2320e4af02ac03d5291 --- /dev/null +++ b/python/dumux/common/fvspatialparams.py @@ -0,0 +1,44 @@ +""" +Finite volume spatial params generator +""" + +from dune.generator.generator import SimpleGenerator +from dune.common.hashit import hashIt + +from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias + + +@cppWrapperCreator +def _createFVSpatialParamsDecorator(gridGeometry): + """A spatial params decorator generator for Python spatial params + + from dumux.common import FVSpatialParams + @FVSpatialParams(gridGeometry) + class MySpatialParams: + ... + """ + + def createModule(): + ggType = gridGeometry._typeName + spatialParamsType = f"Dumux::Python::FVSpatialParams<{ggType}>" + includes = gridGeometry._includes + ["dumux/python/common/fvspatialparams.hh"] + moduleName = "fvspatialparams_" + hashIt(spatialParamsType) + holderType = f"std::shared_ptr<{spatialParamsType}>" + generator = SimpleGenerator("FVSpatialParams", "Dumux::Python") + module = generator.load(includes, spatialParamsType, moduleName, options=[holderType]) + return module + + def decorateFVSpatialParams(cls): + module = createModule() + + def createFVSpatialParams(): + return module.FVSpatialParams(gridGeometry, cls()) + + return createFVSpatialParams + + return decorateFVSpatialParams + + +@cppWrapperClassAlias(creator=_createFVSpatialParamsDecorator) +class FVSpatialParams: + """Class alias used to decorate a Python Finite Volume Spatial Params""" diff --git a/python/dumux/material/CMakeLists.txt b/python/dumux/material/CMakeLists.txt index c6683fdb0b9fc87f479c79f405fa95c1e2703360..71b18100e7f4a4122f07c3cd7667d943f4e009de 100644 --- a/python/dumux/material/CMakeLists.txt +++ b/python/dumux/material/CMakeLists.txt @@ -1,6 +1,5 @@ add_subdirectory(components) add_subdirectory(fluidsystems) -add_subdirectory(spatialparams) add_python_targets(material __init__ diff --git a/python/dumux/material/__init__.py b/python/dumux/material/__init__.py index 01534f242281cf3b905f3a0a44349f4076050a0d..f3a972ef3f7bf558bfff2cbce8e5f92efcef2459 100644 --- a/python/dumux/material/__init__.py +++ b/python/dumux/material/__init__.py @@ -2,4 +2,3 @@ from dumux.material.fluidsystems import FluidSystem from dumux.material.components import Component -from dumux.material.spatialparams import OnePSpatialParams diff --git a/python/dumux/material/spatialparams/CMakeLists.txt b/python/dumux/material/spatialparams/CMakeLists.txt deleted file mode 100644 index db81731a161e443a1c2c0f686cbf84d16af1d2cb..0000000000000000000000000000000000000000 --- a/python/dumux/material/spatialparams/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_python_targets(spatialparams - __init__ -) diff --git a/python/dumux/material/spatialparams/__init__.py b/python/dumux/material/spatialparams/__init__.py deleted file mode 100644 index 49c950458149fd68bc6730bf7792fe9826351cfc..0000000000000000000000000000000000000000 --- a/python/dumux/material/spatialparams/__init__.py +++ /dev/null @@ -1,77 +0,0 @@ -"""Spatial parameter classes""" - -import numpy as np -from dune.generator.generator import SimpleGenerator -from dune.common.hashit import hashIt -from dumux.common import Property -from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias - - -@cppWrapperCreator -def _createOnePSpatialParamsDecorator(*, gridGeometry, scalar: Property = None): - """Turn a Python spatial parameter class into an C++/Python hybrid class""" - - dim = gridGeometry.gridView.dimensionworld - includes = gridGeometry._includes + [ - "dumux/python/material/spatialparams/spatialparams.hh", - "dune/common/fmatrix.hh", - ] - - if scalar is None: - scalar = Property.fromCppType("double") - scalarType = scalar.cppType - - permType = f"Dune::FieldMatrix<{scalarType}, {dim}, {dim}>" - typeName = ( - f"Dumux::Python::FVSpatialParamsOneP<{gridGeometry._typeName}, {scalarType}, {permType}>" - ) - moduleName = f"spatialparams_{hashIt(typeName)}" - - def decorateOnePSpatialParams(cls): - generator = SimpleGenerator("OnePSpatialParams", "Dumux::Python") - module = generator.load(includes, typeName, moduleName, holder="std::shared_ptr") - - def maybeConvertScalarToMatrix(permeabilityValue): - if isinstance(permeabilityValue, float): - matrix = np.zeros(shape=(dim, dim)) - np.fill_diagonal(matrix, permeabilityValue) - return matrix.tolist() - - return permeabilityValue - - class Permeability: - """Permeability decorator to make sure permeability has correct type""" - - def __init__(self, permeabilityFunction): - self.permeabilityFunction = permeabilityFunction - - def __call__(self, element, scv, elemSol): - result = self.permeabilityFunction(element, scv, elemSol) - return maybeConvertScalarToMatrix(result) - - class PermeabilityAtPos: - """PermeabilityAtPos decorator to make sure permeability has correct type""" - - def __init__(self, permeabilityFunction): - self.permeabilityFunction = permeabilityFunction - - def __call__(self, globalPos): - result = self.permeabilityFunction(globalPos) - return maybeConvertScalarToMatrix(result) - - def createSpatialParams(): - spatialParams = cls() - if hasattr(cls, "permeability"): - cls.permeability = Permeability(spatialParams.permeability) - if hasattr(cls, "permeabilityAtPos"): - cls.permeabilityAtPos = PermeabilityAtPos(spatialParams.permeabilityAtPos) - return module.OnePSpatialParams(gridGeometry, spatialParams) - - return createSpatialParams - - return decorateOnePSpatialParams - - -@cppWrapperClassAlias(creator=_createOnePSpatialParamsDecorator) -class OnePSpatialParams: - """Class alias used to decorate Python spatial parameter implementations""" diff --git a/python/dumux/porousmediumflow/__init__.py b/python/dumux/porousmediumflow/__init__.py index 3a4c9c6729a88020ab79122bb672b416a4b07c71..42892d308b317dd4d0ca90ad94b7d273f80eea57 100644 --- a/python/dumux/porousmediumflow/__init__.py +++ b/python/dumux/porousmediumflow/__init__.py @@ -1,7 +1,9 @@ """Classes and functions related to the porousmedium flow models""" +import numpy as np from dune.generator.generator import SimpleGenerator from dune.common.hashit import hashIt +from dumux.common import Property from dumux.wrapping import cppWrapperCreator, cppWrapperClassAlias @@ -24,7 +26,7 @@ def _createPorousMediumFlowProblemDecorator( spType = spatialParams._typeName enableIDC = "true" if enableInternalDirichletConstraints else "false" problemType = ( - "Dumux::Python::PorousMediumFlowProblem" f"<{ggType}, {priVars}, {spType}, {enableIDC}>" + "Dumux::Python::PorousMediumFlowProblem" f"<{ggType}, {spType}, {priVars}, {enableIDC}>" ) includes = [ *(gridGeometry._includes), @@ -79,3 +81,73 @@ def _createPorousMediumFlowVelocityOutput(*, gridVariables): @cppWrapperClassAlias(creator=_createPorousMediumFlowVelocityOutput) class PorousMediumFlowVelocityOutput: """A class alias used to create PorousMediumFlowVelocityOutput instances""" + + +@cppWrapperCreator +def _createFVSpatialParamsOnePDecorator(gridGeometry): + """A spatial params decorator generator for Python spatial params + + from dumux.common import FVSpatialParamsOneP + FVSpatialParamsOneP(gridGeometry) + class MySpatialParams: + ... + """ + dim = gridGeometry.gridView.dimensionworld + scalar = Property.fromCppType("double") + scalarType = scalar.cppType + permType = f"Dune::FieldMatrix<{scalarType}, {dim}, {dim}>" + + def decorateFVSpatialParamsOneP(cls): + ggType = gridGeometry._typeName + spatialParamsType = f"Dumux::Python::FVSpatialParamsOneP<{ggType}, {permType}>" + includes = gridGeometry._includes + ["dumux/python/porousmediumflow/spatialparams.hh"] + includes += ["dumux/python/common/fvspatialparams.hh"] + moduleName = "fvspatialparamsonep_" + hashIt(spatialParamsType) + holderType = f"std::shared_ptr<{spatialParamsType}>" + generator = SimpleGenerator("FVSpatialParamsOneP", "Dumux::Python") + module = generator.load(includes, spatialParamsType, moduleName, options=[holderType]) + + def maybeConvertScalarToMatrix(permeabilityValue): + if isinstance(permeabilityValue, float): + matrix = np.zeros(shape=(dim, dim)) + np.fill_diagonal(matrix, permeabilityValue) + return matrix.tolist() + + return permeabilityValue + + class Permeability: + """Permeability decorator to make sure permeability has correct type""" + + def __init__(self, permeabilityFunction): + self.permeabilityFunction = permeabilityFunction + + def __call__(self, element, scv, elemSol): + result = self.permeabilityFunction(element, scv, elemSol) + return maybeConvertScalarToMatrix(result) + + class PermeabilityAtPos: + """PermeabilityAtPos decorator to make sure permeability has correct type""" + + def __init__(self, permeabilityFunction): + self.permeabilityFunction = permeabilityFunction + + def __call__(self, globalPos): + result = self.permeabilityFunction(globalPos) + return maybeConvertScalarToMatrix(result) + + def createFVSpatialParamsOneP(): + spatialParams = cls() + if hasattr(cls, "permeability"): + cls.permeability = Permeability(spatialParams.permeability) + if hasattr(cls, "permeabilityAtPos"): + cls.permeabilityAtPos = PermeabilityAtPos(spatialParams.permeabilityAtPos) + return module.FVSpatialParamsOneP(gridGeometry, cls()) + + return createFVSpatialParamsOneP + + return decorateFVSpatialParamsOneP + + +@cppWrapperClassAlias(creator=_createFVSpatialParamsOnePDecorator) +class FVSpatialParamsOneP: + """Class alias used to decorate a Python Finite Volume Spatial Params""" diff --git a/test/python/test_1p.py b/test/python/test_1p.py index 89b14accbcd953db2a4c40e8c1115856e78446ae..de0c1d0037f5344fa350199cd87fd02a549adf9c 100755 --- a/test/python/test_1p.py +++ b/test/python/test_1p.py @@ -9,8 +9,12 @@ from dumux.common import initParameters, printParameters, getParam from dumux.common import BoundaryTypes, Model, Property from dumux.discretization import GridGeometry, GridVariables from dumux.assembly import FVAssembler -from dumux.porousmediumflow import PorousMediumFlowProblem, PorousMediumFlowVelocityOutput -from dumux.material import FluidSystem, Component, OnePSpatialParams +from dumux.porousmediumflow import ( + PorousMediumFlowProblem, + PorousMediumFlowVelocityOutput, + FVSpatialParamsOneP, +) +from dumux.material import FluidSystem, Component from dumux.io import VtkOutputModule # Initialize parameters @@ -52,7 +56,7 @@ model["FluidSystem"] = Property.fromInstance(onePLiquid) # Define the spatial parameters -@OnePSpatialParams(gridGeometry=gridGeometry) +@FVSpatialParamsOneP(gridGeometry=gridGeometry) class SpatialParams: dimWorld = gridGeometry.gridView.dimWorld lensLowerLeft = [0.2, 0.2] @@ -80,13 +84,11 @@ class SpatialParams: return 0.4 -# and set them as a model property spatialParams = SpatialParams() model["SpatialParams"] = Property.fromInstance(spatialParams) - # Define the problem -@PorousMediumFlowProblem(gridGeometry, spatialParams) +@PorousMediumFlowProblem(gridGeometry=gridGeometry, spatialParams=spatialParams) class Problem: numEq = 1 @@ -108,12 +110,6 @@ class Problem: def sourceAtPos(self, globalPos): return 0.0 - def extrusionFactor(self, element, scv): - return 1.0 - - def temperatureAtPos(self, globalPos): - return 283.15 - def name(self): return "python_problem" diff --git a/test/python/test_explicit_transport_cctpfa.py b/test/python/test_explicit_transport_cctpfa.py index 4ad605c3a95cd79476cb861f7da1c3289be88567..670716406a7b6ef60a8c2a1db79c026527bac8d3 100755 --- a/test/python/test_explicit_transport_cctpfa.py +++ b/test/python/test_explicit_transport_cctpfa.py @@ -29,12 +29,12 @@ gridGeometry = GridGeometry(gridView, discMethod="cctpfa") elementMapper = gridView.indexSet -############################################## -# Define problem (inital/boundary condtions) # -############################################## +################################################ +# Define problem (initial/boundary conditions) # +################################################ -@FVProblem(gridGeometry) +@FVProblem(gridGeometry=gridGeometry) class Problem: numEq = 1 diff --git a/test/python/test_fvproblem.py b/test/python/test_fvproblem.py index 12adceaad7533c68e212c4251a6e669dc2cc569f..526a23aab23609c52b86366f1656ef86450f949a 100755 --- a/test/python/test_fvproblem.py +++ b/test/python/test_fvproblem.py @@ -27,7 +27,7 @@ gridView = structuredGrid([0, 0, 0], [1, 1, 1], [3, 3, 3]) gridGeometry = GridGeometry(gridView, discMethod="box") -@FVProblem(gridGeometry) +@FVProblem(gridGeometry=gridGeometry) class Problem: numEq = 2