diff --git a/dumux/python/common/parameters.hh b/dumux/python/common/parameters.hh deleted file mode 100644 index d743c69727fbf6f01c60f3f0d3df48c7f2db4675..0000000000000000000000000000000000000000 --- a/dumux/python/common/parameters.hh +++ /dev/null @@ -1,75 +0,0 @@ -// -*- 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 <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief TODO: docme! - */ - -#ifndef DUMUX_PYTHON_COMMON_PARAMETERS_HH -#define DUMUX_PYTHON_COMMON_PARAMETERS_HH - -#include <dumux/common/parameters.hh> - -#include <dune/python/pybind11/pybind11.h> -#include <dune/python/pybind11/stl.h> - -namespace Dumux::Python { - -template <class... options> -void registerParameters(pybind11::handle scope, - pybind11::class_<Parameters, options...> cls) -{ - using pybind11::operator""_a; - - auto setParams = [](const std::unordered_map<std::string, std::string>& params){ - return [&](Dune::ParameterTree& tree){ - for (const auto& p : params) - tree[p.first] = p.second; - }; - }; - - cls.def(pybind11::init([setParams](const std::string& parameterFileName, - const std::unordered_map<std::string, std::string>& params, - bool inputFileOverwritesParams){ - auto p = new Parameters(); - p->init(parameterFileName, setParams(params), inputFileOverwritesParams); - return p; - }) - , "parameterFileName"_a - , "params"_a = std::unordered_map<std::string, std::string>{} - , "inputFileOverwritesParams"_a = false - ); - - cls.def(pybind11::init([setParams](const std::unordered_map<std::string, std::string>& params){ - auto p = new Parameters(); - p->init(setParams(params)); - return p; - })); -} - -template<class Scalar> -void registerParameters(pybind11::handle scope, const char *clsName = "Parameters") -{ - pybind11::class_<Parameters> cls(scope, clsName); - registerParameters(scope, cls); -} - -} // namespace Dumux::Python - -#endif diff --git a/python/dumux/common/__init__.py b/python/dumux/common/__init__.py index 261ff76d6e5bc4af0485c1abae057ac52ee7c52e..872be2ffe593253705e7ee24b1d33ae9b183044c 100644 --- a/python/dumux/common/__init__.py +++ b/python/dumux/common/__init__.py @@ -73,45 +73,3 @@ def _createBoundaryTypes(numEq=1): @cppWrapperClassAlias(creator=_createBoundaryTypes) class BoundaryTypes: """Class alias used to create a BoundaryTypes instance""" - - -@cppWrapperCreator -def _createParameters(params: dict = None, fileName: str = None): - """Create Parameters - - Args: - params (dict): A dictionary of parameter key-value pairs - fileName (str): Optionally a file to read parameters from - - Usage: - parameters = Parameters( - { - "Problem.EnableGravity": True, - "SpatialParams.Porosity": 0.3, - "SpatialParams.Permeability": 1e-8, - "Vtk.AddVelocity": False, - "Assembly.NumericDifference.PriVarMagnitude": 1e5, - } - ) - """ - parametersType = "Dumux::Parameters" - includes = ["dumux/common/parameters.hh", "dumux/python/common/parameters.hh"] - moduleName = "parameters_" + hashIt(parametersType) - generator = SimpleGenerator("Parameters", "Dumux::Python") - module = generator.load(includes, parametersType, moduleName) - - # make sure all dict keys are strings - if params is None: - params = {} - for key, value in params.items(): - params[key] = str(value) - - if fileName is not None: - return module.Parameters(fileName, params) - - return module.Parameters(params) - - -@cppWrapperClassAlias(creator=_createParameters) -class Parameters: - """Class alias used to create a Parameters instance""" diff --git a/python/dumux/common/_common.cc b/python/dumux/common/_common.cc index 49bca345331814d7741894631e309edbd3c166f2..b1a27adffabdbdc77f070a3fd367b565f7d32b0b 100644 --- a/python/dumux/common/_common.cc +++ b/python/dumux/common/_common.cc @@ -18,10 +18,57 @@ *****************************************************************************/ #include <dune/python/pybind11/pybind11.h> +#include <dune/python/pybind11/stl.h> + +#include <dumux/common/parameters.hh> #include <dumux/python/common/timeloop.hh> PYBIND11_MODULE(_common, module) { + using namespace Dumux; + using pybind11::operator""_a; + // export time loop - Dumux::Python::registerTimeLoop<double>(module); + Python::registerTimeLoop<double>(module); + + // initialize the parameters + Parameters::init(); + + // register parameter initializer for command line arguments + // Usage in Python: initParameters(sys.argv, {"bla": "blubb",}) + module.def("initParameters", []( + std::vector<std::string>& argv, + pybind11::dict params, + const std::string& inputFileName + ){ + // convert command line args to compatible format + std::vector<char *> argv_; + for (auto& arg : argv) + argv_.push_back(arg.data()); + + // convert command line args to parameter tree + const auto cmdParams = Parameters::parseCommandLine(argv_.size(), argv_.data()); + + const auto setParams = [&](auto& paramTree){ + paramTree = cmdParams; + for (auto [key, value] : params) + paramTree[pybind11::cast<std::string>(key)] = pybind11::cast<std::string>(pybind11::str(value)); + }; + + if (inputFileName.empty()) + Parameters::init(setParams); + else + Parameters::init(inputFileName, setParams, /*input overwrites params*/false); + + }, "argv"_a, "params"_a = pybind11::dict{}, "inputFileName"_a = ""); + + module.def("getParam", [](const std::string& name){ + return getParam<std::string>(name); + }, "name"_a); + + module.def("getParam", [](const std::string& name, const std::string& defaultValue){ + return getParam<std::string>(name, defaultValue); + }, "name"_a, "default"_a); + + module.def("printParameters", &Parameters::print); } diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 7ac196df1510a0a95cc6e6736dad326d8d133c9c..d0a30c3c799426736483645396076d7e55285ac6 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -27,7 +27,7 @@ dune_python_add_test(NAME test_python_1p_incompressible_box_numdiff --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_1p_box-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/test_1p_box_numeric-00000.vtu - --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py box numeric") + --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py -DiscMethod box -DiffMethod numeric") dune_python_add_test(NAME test_python_1p_incompressible_box_anadiff LABELS python @@ -36,7 +36,7 @@ dune_python_add_test(NAME test_python_1p_incompressible_box_anadiff --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_1p_box-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/test_1p_box_analytic-00000.vtu - --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py box analytic") + --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py -DiscMethod box -DiffMethod analytic") dune_python_add_test(NAME test_python_1p_incompressible_cctpfa_numdiff LABELS python @@ -45,7 +45,7 @@ dune_python_add_test(NAME test_python_1p_incompressible_cctpfa_numdiff --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_1p_cc-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/test_1p_cctpfa_numeric-00000.vtu - --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py cctpfa numeric") + --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py -DiscMethod cctpfa -DiffMethod numeric") dune_python_add_test(NAME test_python_1p_incompressible_cctpfa_anadiff LABELS python @@ -54,4 +54,4 @@ dune_python_add_test(NAME test_python_1p_incompressible_cctpfa_anadiff --script fuzzy --files ${CMAKE_SOURCE_DIR}/test/references/test_1p_cc-reference.vtu ${CMAKE_CURRENT_BINARY_DIR}/test_1p_cctpfa_analytic-00000.vtu - --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py cctpfa analytic") + --command "${CMAKE_CURRENT_SOURCE_DIR}/test_1p.py -DiscMethod cctpfa -DiffMethod analytic") diff --git a/test/python/test_1p.py b/test/python/test_1p.py index 3edbc3e270f8be7a1956dfd8a0d8c2191a2adf06..80ff3088c16cd59e2ac085371dcc5716d01dd257 100755 --- a/test/python/test_1p.py +++ b/test/python/test_1p.py @@ -5,39 +5,32 @@ import sys from dune.grid import structuredGrid from dune.istl import blockVector, CGSolver, SeqSSOR +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.common import BoundaryTypes, Parameters, Model, Property from dumux.porousmediumflow import PorousMediumFlowProblem, PorousMediumFlowVelocityOutput from dumux.material import FluidSystem, Component, OnePSpatialParams from dumux.io import VtkOutputModule -try: - discMethod = sys.argv[1] - diffMethod = sys.argv[2] -except IndexError: - print( - "No discretization method and differentiation method given. Defaulting to box and numeric diff." - ) - discMethod = "box" - diffMethod = "numeric" +# Initialize parameters +initParameters( + argv=sys.argv, + params={ + "Problem.EnableGravity": True, + "Vtk.AddVelocity": False, + "Assembly.NumericDifference.PriVarMagnitude": 1e5, + }, +) +discMethod = getParam("DiscMethod", default="box") if discMethod not in ["box", "cctpfa"]: raise NotImplementedError(discMethod + " not supported yet. Use cctpfa or box") +diffMethod = getParam("DiffMethod", default="numeric") if diffMethod not in ["analytic", "numeric"]: raise NotImplementedError(diffMethod + " must be analytic or numeric") -# Initialize the paramaters -parameters = Parameters( - { - "Problem.EnableGravity": True, - "SpatialParams.Porosity": 0.3, - "SpatialParams.Permeability": 1e-8, - "Vtk.AddVelocity": False, - "Assembly.NumericDifference.PriVarMagnitude": 1e5, - } -) # Set up the grid and the grid geometry gridView = structuredGrid([0, 0], [1, 1], [10, 10]) @@ -46,13 +39,19 @@ gridGeometry = GridGeometry(gridView=gridView, discMethod=discMethod) # Set up the model model = Model(inheritsFrom=["OneP"], gridGeometry=gridGeometry) -# Tell Dumux to use a particular local residual type +# Tell model to use a particular local residual type model["LocalResidual"] = Property.fromCppType( "OnePIncompressibleLocalResidual<TypeTag>", cppIncludes=["dumux/porousmediumflow/1p/incompressiblelocalresidual.hh"], ) +# Setup the fluid system +h20 = Component("SimpleH2O") +onePLiquid = FluidSystem("OnePLiquid", component=h20, scalar=model["Scalar"]) +model["FluidSystem"] = Property.fromInstance(onePLiquid) + +# Define the spatial parameters @OnePSpatialParams(gridGeometry=gridGeometry) class SpatialParams: dimWorld = gridGeometry.gridView.dimWorld @@ -71,24 +70,22 @@ class SpatialParams: def permeability(self, element, scv, elemSol): globalPos = scv.dofPosition # permeability can be either given - # as scalar or tensorial value + # as scalar or tensor if self.isLens(globalPos): return [[1e-12, 0], [0, 1e-12]] - else: - return 1e-10 + + return 1e-10 def porosityAtPos(self, globalPos): return 0.4 +# and set them as a model property spatialParams = SpatialParams() model["SpatialParams"] = Property.fromInstance(spatialParams) -h20 = Component("SimpleH2O") -onePLiquid = FluidSystem("OnePLiquid", component=h20, scalar=model["Scalar"]) -model["FluidSystem"] = Property.fromInstance(onePLiquid) -# define the Problem +# Define the problem @PorousMediumFlowProblem(gridGeometry, spatialParams) class Problem: numEq = 1 @@ -127,10 +124,11 @@ class Problem: return 0 +# and set it as a model property problem = Problem() model["Problem"] = Property.fromInstance(problem) -# initialize the GridVariables and the Assembler +# Initialize the GridVariables and the Assembler gridVars = GridVariables(problem=problem, model=model) assembler = FVAssembler(problem=problem, gridVariables=gridVars, model=model, diffMethod=diffMethod) sol = blockVector(assembler.numDofs) @@ -159,3 +157,6 @@ velocityoutput = PorousMediumFlowVelocityOutput(gridVariables=gridVars) output.addVelocityOutput(velocityoutput) output.addVolumeVariable(lambda vv: vv.pressure(), "p") output.write(1.0) + +# Print used and unused parameters +printParameters()