diff --git a/dumux/common/basicproperties.hh b/dumux/common/basicproperties.hh index cd1c98b46ab25781beea3d15a64260b516954dda..201e251302ada770791ad3a303c9b17317e9d9f3 100644 --- a/dumux/common/basicproperties.hh +++ b/dumux/common/basicproperties.hh @@ -67,6 +67,9 @@ NEW_PROP_TAG(Scalar); //! Property which provides a Dune::ParameterTree. NEW_PROP_TAG(ParameterTree); +//! Property which defines the group that is queried for parameters by default +NEW_PROP_TAG(ModelParameterGroup); + /////////////////////////////////// // Default values for properties: // @@ -113,6 +116,10 @@ bool Property<TypeTag, TTAG(NumericModel), PTAG(ParameterTree)>::initFinished_ = false; +// use the global group as default for the model's parameter group +SET_PROP(NumericModel, ModelParameterGroup) +{ static const char *value() { return ""; }; }; + } // namespace Properties } // namespace Dumux diff --git a/dumux/common/parameters.hh b/dumux/common/parameters.hh index fda6a80cc3c1957c3682a50f832cb09252f138ff..9799c167e635fff41fb1d001e2b0b01cb25c6436 100644 --- a/dumux/common/parameters.hh +++ b/dumux/common/parameters.hh @@ -33,18 +33,32 @@ #include "propertysystem.hh" -#define GET_PARAM(TypeTag, ParamType, ParamName) \ - Dumux::Parameters::Param<TypeTag, PTAG(ParamName), ParamType>::get(#ParamName) +// retrieve a parameter which _does_ have a default value taken from +// the dumux property system. the optional last argument is the group +// name which must be the prefix to the property name which provides +// the default value for the parameter. +#define GET_PARAM(TypeTag, ParamType, ParamName, ...) \ + Dumux::Parameters::Param<TypeTag, PTAG(__VA_ARGS__ ## ParamName), ParamType> \ + :: get(#ParamName, Dumux::Parameters::getGroupName_(#__VA_ARGS__)) + +// retrieve a parameter which does _not_ have a default value taken +// from the dumux property system +//#define GET_RUNTIME_PARAM(TypeTag, ParamType, ParamName) \ +// Dumux::Parameters::RunTimeParam<TypeTag, ParamType>::get(#ParamName) namespace Dumux { namespace Properties { NEW_PROP_TAG(ParameterTree); +NEW_PROP_TAG(ModelParameterGroup); } // namespace Properties namespace Parameters { +const char *getGroupName_(const char *group = "") +{ return group; } + template <class TypeTag, class PropTag, class ParamType> @@ -52,34 +66,104 @@ class Param { typedef typename GET_PROP(TypeTag, PTAG(ParameterTree)) Params; public: - static const ParamType &get(const char *name) + static const ParamType &get(const char *paramName, const char *groupName = "") { - static const ParamType &value = retrieve_(name); +#ifndef NDEBUG + // make sure that a property is only the default for a single + // parameter, i.e. that a property is not used for multiple + // parameters + static std::string fixedGroupName = groupName; + if (fixedGroupName != groupName) + { + DUNE_THROW(Dune::InvalidStateException, + "Conflicting prefixes for parameter '" << paramName + << "': '" << fixedGroupName + << "' and '" << groupName << "'."); + } +#endif + + static const ParamType &value = retrieve_(paramName, groupName); return value; } private: - static const ParamType &retrieve_(const char *name) + static const ParamType &retrieve_(const char *paramName, const char *groupName) { + // prefix the parameter name by 'GroupName.'. E.g. 'Newton' + // and 'WriteConvergence' becomes 'Newton.WriteConvergence' + // with the default value specified by the + // 'NewtonWriteConvergence' property. in an INI file this + // would look like: + // + // [Newton] + // WriteConvergence = true + std::string finalName(paramName); + int groupNameLen = strlen(groupName); + if (groupNameLen) { + finalName.insert(0, "."); + finalName.insert(0, groupName); + } + + std::string modelParamGroup(GET_PROP(TypeTag, PTAG(ModelParameterGroup))::value()); + // prefix the parameter with the parameter group of the + // model. this allows things like sub-model specific parameters like + // + // [Stokes.Newton] + // WriteConvergence = false + // [Darcy.Newton] + // WriteConvergence = true + if (modelParamGroup.size()) { + finalName.insert(0, "."); + finalName.insert(0, modelParamGroup); + } + + // retrieve actual parameter from the parameter tree ParamType defaultValue = GET_PROP_VALUE(TypeTag, PropTag); - static ParamType value = Params::tree().template get<ParamType>(name, defaultValue); + static ParamType value = Params::tree().template get<ParamType>(finalName, defaultValue); + // remember whether the parameter was taken from the parameter + // tree or the default from the property system was taken. Dune::ParameterTree &rt = Params::tree().sub("RunTimeParams"); Dune::ParameterTree &ct = Params::tree().sub("DefaultParams"); - if (Params::tree().hasKey(name)) { - rt[name] = Params::tree()[name]; + if (Params::tree().hasKey(finalName)) { + rt[finalName] = Params::tree()[finalName]; } else { std::string s; std::ostringstream oss(s); oss << defaultValue; - ct[name] = oss.str(); + ct[finalName] = oss.str(); } return value; } }; +template <class TypeTag, + class ParamType> +class RunTimeParam +{ + typedef typename GET_PROP(TypeTag, PTAG(ParameterTree)) Params; +public: + static const ParamType &get(const char *name) + { + static const ParamType &value = retrieve_(name); + return value; + } + +private: + static const ParamType &retrieve_(const char *name) + { + static ParamType value = Params::tree().template get<ParamType>(name); + + Dune::ParameterTree &rt = Params::tree().sub("RunTimeParams"); + if (Params::tree().hasKey(name)) { + rt[name] = Params::tree()[name]; + } + + return value; + } +}; } // namespace Parameters diff --git a/dumux/nonlinear/newtoncontroller.hh b/dumux/nonlinear/newtoncontroller.hh index 78472ad68fcb2e92a01eb50d434355534ce474c8..3b128237de5c85363c1154bad6a5047ceb535cb6 100644 --- a/dumux/nonlinear/newtoncontroller.hh +++ b/dumux/nonlinear/newtoncontroller.hh @@ -168,20 +168,20 @@ public: enablePartialReassemble_ = GET_PARAM(TypeTag, bool, EnablePartialReassemble); enableJacobianRecycling_ = GET_PARAM(TypeTag, bool, EnableJacobianRecycling); - useLineSearch_ = GET_PARAM(TypeTag, bool, NewtonUseLineSearch); - enableRelativeCriterion_ = GET_PARAM(TypeTag, bool, NewtonEnableRelativeCriterion); - enableAbsoluteCriterion_ = GET_PARAM(TypeTag, bool, NewtonEnableAbsoluteCriterion); - satisfyAbsAndRel_ = GET_PARAM(TypeTag, bool, NewtonSatisfyAbsAndRel); + useLineSearch_ = GET_PARAM(TypeTag, bool, UseLineSearch, Newton); + enableRelativeCriterion_ = GET_PARAM(TypeTag, bool, EnableRelativeCriterion, Newton); + enableAbsoluteCriterion_ = GET_PARAM(TypeTag, bool, EnableAbsoluteCriterion, Newton); + satisfyAbsAndRel_ = GET_PARAM(TypeTag, bool, SatisfyAbsAndRel, Newton); if (!enableRelativeCriterion_ && !enableAbsoluteCriterion_) { DUNE_THROW(Dune::NotImplemented, "at least one of NewtonEnableRelativeCriterion or " << "NewtonEnableAbsoluteCriterion has to be set to true"); } - setRelTolerance(GET_PARAM(TypeTag, Scalar, NewtonRelTolerance)); - setAbsTolerance(GET_PARAM(TypeTag, Scalar, NewtonAbsTolerance)); - setTargetSteps(GET_PARAM(TypeTag, int, NewtonTargetSteps)); - setMaxSteps(GET_PARAM(TypeTag, int, NewtonMaxSteps)); + setRelTolerance(GET_PARAM(TypeTag, Scalar, RelTolerance, Newton)); + setAbsTolerance(GET_PARAM(TypeTag, Scalar, AbsTolerance, Newton)); + setTargetSteps(GET_PARAM(TypeTag, int, TargetSteps, Newton)); + setMaxSteps(GET_PARAM(TypeTag, int, MaxSteps, Newton)); verbose_ = true; numSteps_ = 0; @@ -302,7 +302,7 @@ public: method_ = &method; numSteps_ = 0; - if (GET_PARAM(TypeTag, bool, NewtonWriteConvergence)) + if (GET_PARAM(TypeTag, bool, WriteConvergence, Newton)) convergenceWriter_.beginTimestep(); } @@ -496,7 +496,7 @@ public: */ void newtonEnd() { - if (GET_PARAM(TypeTag, bool, NewtonWriteConvergence)) + if (GET_PARAM(TypeTag, bool, WriteConvergence, Newton)) convergenceWriter_.endTimestep(); } @@ -639,7 +639,7 @@ protected: void writeConvergence_(const SolutionVector &uLastIter, const SolutionVector &deltaU) { - if (GET_PARAM(TypeTag, bool, NewtonWriteConvergence)) { + if (GET_PARAM(TypeTag, bool, WriteConvergence, Newton)) { convergenceWriter_.beginIteration(this->gridView_()); convergenceWriter_.writeFields(uLastIter, deltaU); convergenceWriter_.endIteration();