Newer
Older
// This file is part of the dune-xt-common project:
// https://github.com/dune-community/dune-xt-common
// Copyright 2009-2018 dune-xt-common developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
// or GPL-2.0+ (http://opensource.org/licenses/gpl-license)
// with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
// René Fritze (2018)
// Tobias Leibner (2017 - 2018)
#include "config.h"
#include <algorithm>
#include <sstream>
#include <type_traits>
#include "exceptions.hh"
#include "parameter.hh"
namespace Dune {
namespace XT {
namespace Common {
namespace internal {
// ========================
// ========================
template class SimpleDict<size_t>;
template class SimpleDict<std::vector<double>>;
} // namespace internal
// =========================
// ===== ParameterType =====
// =========================
ParameterType::ParameterType()
: BaseType()
ParameterType::ParameterType(const std::string& key)
: BaseType(key, 1)
ParameterType::ParameterType(const std::string& key, const size_t& sz)
: BaseType(key, sz)
ParameterType::ParameterType(const std::pair<std::string, size_t>& key_size_pair)
: BaseType(key_size_pair.first, key_size_pair.second)
ParameterType::ParameterType(const std::pair<const char*, int>& key_size_pair)
: BaseType(std::string(key_size_pair.first), numeric_cast<size_t>(key_size_pair.second))
ParameterType::ParameterType(const std::vector<std::pair<std::string, size_t>>& key_size_pairs)
: BaseType(key_size_pairs)

Dr. Felix Tobias Schindler
committed
ParameterType::ParameterType(BaseType&& source)
: BaseType(std::move(source))

Dr. Felix Tobias Schindler
committed
ParameterType ParameterType::operator+(const ParameterType& other) const
{
return this->merge(other,
[](const auto& left, const auto& right) { return left == right; },
[](const auto& /*left*/, const auto& /*right*/) {
return "cannot add parameter types which contain the same key with different sizes:";
});
} // ... operator+(...)
bool ParameterType::operator==(const ParameterType& other) const
{
if (this->size() == 1 && other.size() == 1) {
const auto& this_single_element = *this->dict_.begin();
const auto& other_single_element = *other.dict_.begin();
if (this_single_element.first == other_single_element.first || this_single_element.first == "__unspecified__"
|| other_single_element.first == "__unspecified__") {
return this_single_element.second == other_single_element.second;
} else {
return false;
}
} else {
return this->dict_ == other.dict_;
}
} // ... operator==(...)
bool ParameterType::operator!=(const ParameterType& other) const
{
return !(*this == other);
}
bool ParameterType::operator<(const ParameterType& other) const
{
if (this->dict_.size() >= other.dict_.size())
return false;
for (const auto& this_element : this->dict_) {
const auto& this_key = this_element.first;
const auto& this_keys_lenght = this_element.second;
const auto other_key_search_result = other.dict_.find(this_key);

Dr. Felix Tobias Schindler
committed
if (other_key_search_result == other.dict_.end())
return false;
const auto& other_key_lenght = other_key_search_result->second;
if (other_key_lenght != this_keys_lenght)
return false;
}
// now we know that
// - each of our keys is contained in other
// - our length for each key equals the length of others keys
// - other contains more keys
return true;
} // ... operator<(...)
bool ParameterType::operator<=(const ParameterType& other) const
{
return *this < other || *this == other;
}
std::string ParameterType::report() const
{
return "ParameterType(" + BaseType::report("ParameterType(") + ")";
}
std::ostream& operator<<(std::ostream& out, const ParameterType& param_type)
{
out << param_type.report();
return out;
}
// =====================
// ===== Parameter =====
// =====================
Parameter::Parameter(const double& value)
: BaseType("__unspecified__", {value})
Parameter::Parameter(const std::vector<double>& value)
: BaseType("__unspecified__", value)
Parameter::Parameter(const std::string& key, const double& value)
: BaseType(key, {value})
Parameter::Parameter(const std::string& key, const ValueType& value)
: BaseType(key, value)
Parameter::Parameter(const std::vector<std::pair<std::string, ValueType>>& key_value_pairs)
: BaseType(key_value_pairs)
Parameter::Parameter(const std::initializer_list<std::pair<std::string, ValueType>>& key_value_pairs)
: BaseType(key_value_pairs)

Dr. Felix Tobias Schindler
committed
Parameter::Parameter(BaseType&& source)
: BaseType(std::move(source))

Dr. Felix Tobias Schindler
committed
Parameter Parameter::operator+(const Parameter& other) const
{
return this->merge(other,
[](const auto& left, const auto& right) {
if (left.size() != right.size())
return false;
return FloatCmp::eq(left, right);
},
[](const auto& left, const auto& right) {
if (left.size() != right.size())
return "cannot add parameters which contain the same key with different sizes:";
else
return "cannot add parameters which contain the same key with different values:";
});
} // ... operator+(...)
bool Parameter::operator<(const Parameter& other) const
{
return this->dict_ < other.dict_;
}
ParameterType Parameter::type() const
{
ParameterType ret;
for (const auto key_value_pairs : dict_)
ret.set(key_value_pairs.first, key_value_pairs.second.size());
return ret;
}
std::string Parameter::report() const
{
return "Parameter(" + BaseType::report("Parameter(") + ")";
}
std::ostream& operator<<(std::ostream& out, const Parameter& mu)
{
out << mu.report();
return out;
}
// ===============================
// ===== ParametricInterface =====
// ===============================
ParametricInterface::ParametricInterface(const ParameterType& param_type)
: parameter_type_(param_type)
bool ParametricInterface::is_parametric() const
{

Dr. Felix Tobias Schindler
committed
return !parameter_type().empty();
}
const ParameterType& ParametricInterface::parameter_type() const
{
return parameter_type_;
Parameter ParametricInterface::parse_parameter(const Parameter& mu) const
{
const auto& this_type = this->parameter_type();
const auto& mus_type = mu.type();
if (this_type.size() == 1 && mus_type.size() == 1) {
// both have only one key, so either key might be '__unspecified__'
const auto this_single_key = this_type.keys().at(0);
const auto mus_single_key = mus_type.keys().at(0);
if (this_single_key == mus_single_key)
if (this_single_key == "__unspecified__") {
return mu;
} else if (mus_single_key == "__unspecified__") {
return Parameter(this_single_key, mu.get("__unspecified__"));
// both have only one key, but the keys don't match and neither is '__unspecified__'
DUNE_THROW(Exceptions::parameter_error,
"this->parameter_type() = " << this_type << "\n "
// one of them has more than one key, so '__unspecified__' does not play a role here
if (this_type <= mus_type)
return mu;
DUNE_THROW(Exceptions::parameter_error,
"this->parameter_type() = " << this_type << "\n "
return Parameter();
} // ... parse_parameter(...)
void ParametricInterface::extend_parameter_type(const ParameterType& additional_parameter_type)
{
try {
this->parameter_type_ = this->parameter_type() + additional_parameter_type;
} catch (Exceptions::parameter_error& ee) {
DUNE_THROW(Exceptions::parameter_error, "Error extending parameter type:\n " << ee.what());
}
} // ... extend_parameter_type(...)
} // namespace Common
} // namespace XT
} // namespace Dune